📄 o_timeout.c,v
字号:
head 1.1;access;symbols;locks; strict;comment @ * @;1.1date 2002.07.02.19.30.05; author rbraud; state Exp;branches;next ;desc@@1.1log@Initial revision@text@/* * timeout.c -- aux routines for timeouts. * * PURIFY FIX: Many things. * - It was possible for timeout structure blocks to be reallocated without * being freed first. Fixed this. * - Signals were not being block consistantly. I made it so that signals * are only blocking in the entry-point functions, and not in all of the * utility functions. * - It was possible for a timer to expire in this code just after the timer * was canceled in hwt.c * - Got rid of unused functions and commented out code for clarity. * - Made the code easier to read. */#include <signal.h>#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include "general.h"#include "util.h"#include "utilDebug.h"//#include "sys/o_threads.h"#include "o_timeout.h"#define NTOPERBLK 500#define MAXTOBLK 60static timeout_t *timeouts[MAXTOBLK];static timeout_t *pending_timeouts;static int timeout_hw = 0;static int num_blocks = 0;static int beating = 0;//static o_thread_mutex to_mutex;//static o_thread_mutex pt_mutex;//static o_thread_mutex hb_mutex;static sigset_t timer_mask;static sigset_t orig_mask;static int mask_set = FALSE; // To ensure that the mask is set only once./*==========================================================================*/void UTIL_check(int cond, char *msg){ /* * Check condition "cond", exit if zero. */ if (!cond) { fprintf(stderr, "Fatal error in File %s at line %d: %s\n", __FILE__, __LINE__, msg); exit(3); }}/*==========================================================================*/void init_timer_mask(){ sigemptyset(&timer_mask); sigemptyset(&orig_mask); sigaddset(&timer_mask, SIGALRM); sigprocmask(0x0, 0x0, &orig_mask); /* Get the current mask. */}/*==========================================================================*/int mask_timer(void){ if(mask_set == FALSE) { mask_set = TRUE; sigprocmask(SIG_BLOCK, &timer_mask, &orig_mask); // pthread_sigmask(SIG_BLOCK, &timer_mask, &orig_mask); return CALL_UNMASK_TIMER; } else return DONT_CALL_UNMASK_TIMER;}/*==========================================================================*/void unmask_timer(void){ sigprocmask(SIG_SETMASK, &orig_mask, 0x0); // pthread_sigmask(SIG_SETMASK, &orig_mask, 0x0); mask_set = FALSE; }/*==========================================================================*/timeout_t *alloc_timeout(){ timeout_t *tp; int nblk; int i; int j; /* * Get a new timeout structure. This function should never return NULL. */ nblk = (timeout_hw / NTOPERBLK); // o_thr_mutex_lock(&to_mutex); while (nblk >= num_blocks) { /* * Time to allocate more timeout structures. */ UTIL_check((num_blocks < MAXTOBLK), "Too many Timeouts!"); timeouts[num_blocks] = (timeout_t *)calloc(NTOPERBLK, sizeof(timeout_t)); num_blocks++; } /* * Do a linear search for a free timeout structure. */ for (i = 0; i <= nblk; i++) { tp = timeouts[i]; for (j = 0; j < NTOPERBLK; j++) { if (tp->to_busy == 0) { tp->to_next = NULL; tp->to_prev = NULL; tp->to_busy = 1; timeout_hw++; // o_thr_mutex_unlock(&to_mutex); return(tp); } tp++; } } // o_thr_mutex_unlock(&to_mutex); UTIL_check(0, "Didn't find a free timeout!"); return(NULL);}/*==========================================================================*/void free_timeout_unprot(timeoutHandle_t tp){ UTIL_check((tp != NULL), "Tried to free a NULL timeout."); /* * Set the busy flag to 0 and decrement the number of timeout structures * currently allocated. */ tp->to_busy = 0; timeout_hw--;}/*==========================================================================*/void free_timeout(timeoutHandle_t tp){ /* * Get the to mutex lock, then free it. */ // o_thr_mutex_lock(&to_mutex); free_timeout_unprot(tp); // o_thr_mutex_unlock(&to_mutex);}/*==========================================================================*/void _heartbeat(int a){ timeout_t *tp; /* * Attempt to get all of the locks. If we cannot get any of the locks, then * return so as to not hold up the timer. Note that SIGALRM is * automatically blocked due to the use of ualarm() and the sa_mask * specified in sigaction(). */ /* if (o_thr_mutex_trylock(&hb_mutex) != 0) { return; } if (o_thr_mutex_trylock(&pt_mutex) != 0) { o_thr_mutex_unlock(&hb_mutex); return; } if (o_thr_mutex_trylock(&to_mutex) != 0) { o_thr_mutex_unlock(&hb_mutex); o_thr_mutex_unlock(&pt_mutex); return; } */ /* * Handle callouts, if any. */ if (pending_timeouts != NULL) { pending_timeouts->to_ticks -= 1; /* Another tick of the clock. */ while ((pending_timeouts != NULL) && (pending_timeouts->to_ticks == 0)) { /* * Some have expired. */ tp = pending_timeouts; /* * Take tp out of the pending timeouts linked list and reset * pending_timeouts. */ if (tp->to_next != NULL) { tp->to_next->to_prev = NULL; } pending_timeouts = tp->to_next; /* * Perform the callback, unlocking the pt and to mutexes to allow the * callback funstion to set and cancel timers. */ // o_thr_mutex_unlock(&to_mutex); // o_thr_mutex_unlock(&pt_mutex); (tp->to_fun)(tp->to_arg1); // o_thr_mutex_lock(&pt_mutex); // o_thr_mutex_lock(&to_mutex); /* * Free the expired timeout. */ free_timeout_unprot(tp); } } // o_thr_mutex_unlock(&to_mutex); // o_thr_mutex_unlock(&pt_mutex); // o_thr_mutex_unlock(&hb_mutex);}/*==========================================================================*/void start_heartbeat(){ struct sigaction act; /* * Only start the heartbeat once. */ if (!beating) { #ifdef THREADED UTIL_check(0, "Please update the starthb() routine.");#else act.sa_handler = _heartbeat; act.sa_flags = 0; act.sa_flags |= SA_RESTART; #ifdef linux act.sa_handler = _heartbeat;#endif #ifdef solaris2 act.sa_sigaction = _heartbeat;#endif sigemptyset(&act.sa_mask); sigaddset(&act.sa_mask, SIGPOLL); sigaddset(&act.sa_mask, SIGALRM); sigaction(SIGALRM, &act, 0x0); UTIL_check(((long)ualarm(USEC_PER_TICK, USEC_PER_TICK) != -1L), "Unable to start interval alarm."); #endif beating++; }}/*==========================================================================*/void enqueue_timeout(timeoutHandle_t p){ timeout_t *pp; timeout_t *lp; int pval; /* * Add p to the pending_timeouts list. */ if (p == NULL) { // UTIL_InfoMessage(UTIL_ERROR, "enqueue_timeout called with null timeout"); return; } // o_thr_mutex_lock(&pt_mutex); if ((pp = pending_timeouts) == NULL) { pending_timeouts = p; // o_thr_mutex_unlock(&pt_mutex); return; } /* * p and pp are non-NULL. Something is currently on the list. Find the * first entry to expire AFTER the new one. */ lp = NULL; pval = p->to_ticks; while ((pval > pp->to_ticks) && (pp->to_next != NULL)) { /* * Both (pp != NULL) and (pp->to_next != NULL). */ lp = pp; pval -= pp->to_ticks; pp = pp->to_next; } /* * Either (pval <= pp->to_ticks) or (pp->to_next == NULL). */ if (pval > pp->to_ticks) { /* * New entry is the last in the list. */ pval -= pp->to_ticks; /* One more decrement. */ p->to_ticks = pval; p->to_prev = pp; p->to_next = NULL; pp->to_next = p; // o_thr_mutex_unlock(&pt_mutex); return; } /* * New entry is not the last in the list. */ p->to_next = pp; p->to_prev = lp; p->to_ticks = pval; pp->to_ticks -= pval; /* Decrement the rest of the values. */ pp->to_prev = p; if (lp == NULL) { pending_timeouts = p; } else { lp->to_next = p; } // o_thr_mutex_unlock(&pt_mutex); return;}/*==========================================================================*/void initTimeout(){ /* * Set up the timeout code and data. */ pending_timeouts = NULL; /* Set the debug file pointer for UTIL_XXX functions to be "stderr" */ // UTIL_SetDebugFile(stderr); // o_thr_mutex_init(&to_mutex, NULL); // o_thr_mutex_init(&pt_mutex, NULL); // o_thr_mutex_init(&hb_mutex, NULL); init_timer_mask(); start_heartbeat();}/*==========================================================================*/timeoutHandle_t startTimer(int t, void (*func)(int), int arg1, int arg2){ timeout_t *tp; //int call_unmask_timer; /* * Arrange for func to be called with argument arg in t "ticks". */ UTIL_check(beating, "StartTimer called before initTimeout."); UTIL_check((t > 0), "StartTimer called with nonpositive arg."); //call_unmask_timer = mask_timer(); tp = alloc_timeout(); tp->to_ticks = t; tp->to_fun = func; tp->to_arg1 = arg1; tp->to_arg2 = arg2; enqueue_timeout(tp); //if(call_unmask_timer == CALL_UNMASK_TIMER) // unmask_timer(); return(tp);}/*==========================================================================*/int cancelTimer(timeoutHandle_t tim){ /* * Return val: 0 == OK * -1 == Never heard of it */ //int call_unmask_timer; if (tim == NULL) { return(1); } //call_unmask_timer = mask_timer(); // o_thr_mutex_lock(&to_mutex); if (tim->to_busy == 0) { // o_thr_mutex_unlock(&to_mutex); // if(call_unmask_timer == CALL_UNMASK_TIMER) // unmask_timer(); return(-1); } // o_thr_mutex_unlock(&to_mutex); // o_thr_mutex_lock(&pt_mutex); if (tim->to_next != NULL) { /* * There is a next timeout entry. */ tim->to_next->to_prev = tim->to_prev; tim->to_next->to_ticks += tim->to_ticks; /* Add time to next entry. */ } if (tim->to_prev != NULL) { /* * Not the first element. */ tim->to_prev->to_next = tim->to_next; } else { /* * First in the list. */ pending_timeouts = tim->to_next; } // o_thr_mutex_unlock(&pt_mutex); free_timeout(tim); //if(call_unmask_timer == CALL_UNMASK_TIMER) // unmask_timer(); return(0);}@
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -