Annotation of embedaddon/pimdd/callout.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * The mrouted program is covered by the license in the accompanying file
                      3:  * named "LICENSE.mrouted". Use of the mrouted program represents acceptance
                      4:  * of the terms and conditions listed in that file.
                      5:  *
                      6:  * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
                      7:  * Leland Stanford Junior University.
                      8:  *
                      9:  *
                     10:  * callout.c,v 3.8.4.5 1997/05/16 20:18:25 fenner Exp
                     11:  */
                     12: 
                     13: #include "defs.h"
                     14: 
                     15: /* the code below implements a callout queue */
                     16: static int id = 0;
                     17: static struct timeout_q  *Q = 0; /* pointer to the beginning of timeout queue */
                     18: 
                     19: struct timeout_q {
                     20:     struct timeout_q *next;            /* next event */
                     21:     int                     id;  
                     22:     cfunc_t          func;             /* function to call */
                     23:     void            *data;             /* func's data */
                     24:     int              time;             /* time offset to next event*/
                     25: };
                     26: 
                     27: #ifdef CALLOUT_DEBUG
                     28: static void print_Q __P((void));
                     29: #else
                     30: #define        print_Q()       
                     31: #endif
                     32: 
                     33: void
                     34: callout_init()
                     35: {
                     36:     Q = (struct timeout_q *) 0;
                     37: }
                     38: 
                     39: void
                     40: free_all_callouts()
                     41: {
                     42:     struct timeout_q *p;
                     43:     
                     44:     while (Q) {
                     45:        p = Q;
                     46:        Q = Q->next;
                     47:        free(p);
                     48:     }
                     49: }
                     50: 
                     51: 
                     52: /*
                     53:  * elapsed_time seconds have passed; perform all the events that should
                     54:  * happen.
                     55:  */
                     56: void
                     57: age_callout_queue(elapsed_time)
                     58:     int elapsed_time;
                     59: {
                     60:     struct timeout_q *ptr, *expQ;
                     61:     
                     62: #ifdef CALLOUT_DEBUG
                     63:     IF_DEBUG(DEBUG_TIMEOUT)
                     64:        log(LOG_DEBUG, 0, "aging queue (elapsed time %d):", elapsed_time);
                     65:     print_Q();
                     66: #endif
                     67: 
                     68:     expQ = Q;
                     69:     ptr = NULL;
                     70:     
                     71:     while (Q) {
                     72:        if (Q->time > elapsed_time) {
                     73:            Q->time -= elapsed_time;
                     74:            if (ptr) {
                     75:                ptr->next = NULL;
                     76:                break;
                     77:            }
                     78:            return;
                     79:        } else {
                     80:            elapsed_time -= Q->time;
                     81:            ptr = Q;
                     82:            Q = Q->next;
                     83:        }
                     84:     }
                     85:     
                     86:     /* handle queue of expired timers */
                     87:     while (expQ) {
                     88:        ptr = expQ;
                     89:        if (ptr->func)
                     90:            ptr->func(ptr->data);
                     91:        expQ = expQ->next;
                     92:        free(ptr);
                     93:     }
                     94: }
                     95: 
                     96: /*
                     97:  * Return in how many seconds age_callout_queue() would like to be called.
                     98:  * Return -1 if there are no events pending.
                     99:  */
                    100: int
                    101: timer_nextTimer()
                    102: {
                    103:     if (Q) {
                    104:        if (Q->time < 0) {
                    105:            log(LOG_WARNING, 0, "timer_nextTimer top of queue says %d", 
                    106:                Q->time);
                    107:            return 0;
                    108:        }
                    109:        return Q->time;
                    110:     }
                    111:     return -1;
                    112: }
                    113: 
                    114: /* 
                    115:  * sets the timer
                    116:  */
                    117: int
                    118: timer_setTimer(delay, action, data)
                    119:     int        delay;          /* number of units for timeout */
                    120:     cfunc_t    action;         /* function to be called on timeout */
                    121:     void       *data;          /* what to call the timeout function with */
                    122: {
                    123:     struct     timeout_q  *ptr, *node, *prev;
                    124:     
                    125: #ifdef CALLOUT_DEBUG
                    126:     IF_DEBUG(DEBUG_TIMEOUT)
                    127:        log(LOG_DEBUG, 0, "setting timer:");
                    128:     print_Q();
                    129: #endif
                    130: 
                    131:     /* create a node */        
                    132:     node = (struct timeout_q *)malloc(sizeof(struct timeout_q));
                    133:     if (node == 0) {
                    134:        log(LOG_WARNING, 0, "Malloc Failed in timer_settimer\n");
                    135:        return -1;
                    136:     }
                    137:     node->func = action; 
                    138:     node->data = data;
                    139:     node->time = delay; 
                    140:     node->next = 0;    
                    141:     node->id   = ++id;
                    142:     
                    143:     prev = ptr = Q;
                    144:     
                    145:     /* insert node in the queue */
                    146:     
                    147:     /* if the queue is empty, insert the node and return */
                    148:     if (!Q)
                    149:        Q = node;
                    150:     else {
                    151:        /* chase the pointer looking for the right place */
                    152:        while (ptr) {
                    153:            
                    154:            if (delay < ptr->time) {
                    155:                /* right place */
                    156:                
                    157:                node->next = ptr;
                    158:                if (ptr == Q)
                    159:                    Q = node;
                    160:                else
                    161:                    prev->next = node;
                    162:                ptr->time -= node->time;
                    163:                return node->id;
                    164:            } else  {
                    165:                /* keep moving */
                    166:                
                    167:                delay -= ptr->time; node->time = delay;
                    168:                prev = ptr;
                    169:                ptr = ptr->next;
                    170:            }
                    171:        }
                    172:        prev->next = node;
                    173:     }
                    174:     return node->id;
                    175: }
                    176: 
                    177: /* returns the time until the timer is scheduled */
                    178: int
                    179: timer_leftTimer(timer_id)
                    180:     int timer_id;
                    181: {
                    182:     struct timeout_q *ptr;
                    183:     int left = 0;
                    184:        
                    185:     if (!timer_id)
                    186:        return -1;
                    187:     
                    188:     for (ptr = Q; ptr; ptr = ptr->next) {
                    189:        left += ptr->time;
                    190:        if (ptr->id == timer_id)
                    191:            return left;
                    192:     }
                    193:     return -1;
                    194: }
                    195: 
                    196: /* clears the associated timer */
                    197: void
                    198: timer_clearTimer(timer_id)
                    199:     int  timer_id;
                    200: {
                    201:     struct timeout_q  *ptr, *prev;
                    202:     
                    203:     if (!timer_id)
                    204:        return;
                    205:     
                    206:     prev = ptr = Q;
                    207:     
                    208:     /*
                    209:      * find the right node, delete it. the subsequent node's time
                    210:      * gets bumped up
                    211:      */
                    212:     
                    213:     while (ptr) {
                    214:        if (ptr->id == timer_id) {
                    215:            /* got the right node */
                    216:            
                    217:            /* unlink it from the queue */
                    218:            if (ptr == Q)
                    219:                Q = Q->next;
                    220:            else
                    221:                prev->next = ptr->next;
                    222:            
                    223:            /* increment next node if any */
                    224:            if (ptr->next != 0)
                    225:                (ptr->next)->time += ptr->time;
                    226:            
                    227:            if (ptr->data)
                    228:                free(ptr->data);
                    229:            free(ptr);
                    230:            return;
                    231:        }
                    232:        prev = ptr;
                    233:        ptr = ptr->next;
                    234:     }
                    235: }
                    236: 
                    237: #ifdef CALLOUT_DEBUG
                    238: /*
                    239:  * debugging utility
                    240:  */
                    241: static void
                    242: print_Q()
                    243: {
                    244:     struct timeout_q  *ptr;
                    245:     
                    246:     IF_DEBUG(DEBUG_TIMEOUT)
                    247:        for (ptr = Q; ptr; ptr = ptr->next)
                    248:            log(LOG_DEBUG, 0, "(%d,%d) ", ptr->id, ptr->time);
                    249: }
                    250: #endif /* CALLOUT_DEBUG */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>