Annotation of embedaddon/pimd/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: #if 0
                     28: #define CALLOUT_DEBUG 1
                     29: #define CALLOUT_DEBUG2 1
                     30: #endif /* 0 */
                     31: #ifdef CALLOUT_DEBUG2
                     32: static void print_Q((void);
                     33: #else
                     34: #define        print_Q()       
                     35: #endif
                     36: 
                     37: void
                     38: callout_init()
                     39: {
                     40:     Q = (struct timeout_q *) 0;
                     41: }
                     42: 
                     43: void
                     44: free_all_callouts()
                     45: {
                     46:     struct timeout_q *p;
                     47:     
                     48:     while (Q) {
                     49:        p = Q;
                     50:        Q = Q->next;
                     51:        free(p);
                     52:     }
                     53: }
                     54: 
                     55: 
                     56: /*
                     57:  * elapsed_time seconds have passed; perform all the events that should
                     58:  * happen.
                     59:  */
                     60: void
                     61: age_callout_queue(elapsed_time)
                     62:     int elapsed_time;
                     63: {
                     64:     struct timeout_q *ptr, *expQ;
                     65:     
                     66: #ifdef CALLOUT_DEBUG
                     67:     IF_DEBUG(DEBUG_TIMEOUT)
                     68:        logit(LOG_DEBUG, 0, "aging queue (elapsed time %d):", elapsed_time);
                     69:     print_Q();
                     70: #endif
                     71:     
                     72:     expQ = Q;
                     73:     ptr = NULL;
                     74:     
                     75:     while (Q) {
                     76:        if (Q->time > elapsed_time) {
                     77:            Q->time -= elapsed_time;
                     78:            if (ptr) {
                     79:                ptr->next = NULL;
                     80:                break;
                     81:            }
                     82:            return;
                     83:        } else {
                     84:            elapsed_time -= Q->time;
                     85:            ptr = Q;
                     86:            Q = Q->next;
                     87:        }
                     88:     }
                     89:     
                     90:     /* handle queue of expired timers */
                     91:     while (expQ) {
                     92:        ptr = expQ;
                     93:        if (ptr->func)
                     94:            ptr->func(ptr->data);
                     95:        expQ = expQ->next;
                     96:        free(ptr);
                     97:     }
                     98: }
                     99: 
                    100: /*
                    101:  * Return in how many seconds age_callout_queue() would like to be called.
                    102:  * Return -1 if there are no events pending.
                    103:  */
                    104: int
                    105: timer_nextTimer()
                    106: {
                    107:     if (Q) {
                    108:        if (Q->time < 0) {
                    109:            logit(LOG_WARNING, 0, "timer_nextTimer top of queue says %d", 
                    110:                Q->time);
                    111:            return 0;
                    112:        }
                    113:        return Q->time;
                    114:     }
                    115:     return -1;
                    116: }
                    117: 
                    118: /* 
                    119:  * sets the timer
                    120:  */
                    121: int
                    122: timer_setTimer(delay, action, data)
                    123:     int        delay;          /* number of units for timeout */
                    124:     cfunc_t    action;         /* function to be called on timeout */
                    125:     void       *data;          /* what to call the timeout function with */
                    126: {
                    127:     struct     timeout_q  *ptr, *node, *prev;
                    128:     
                    129: #ifdef CALLOUT_DEBUG
                    130:     IF_DEBUG(DEBUG_TIMEOUT)
                    131:        logit(LOG_DEBUG, 0, "setting timer:");
                    132:     print_Q();
                    133: #endif
                    134:     
                    135:     /* create a node */        
                    136:     node = (struct timeout_q *)calloc(1, sizeof(struct timeout_q));
                    137:     if (!node) {
                    138:        logit(LOG_ERR, 0, "Failed calloc() in timer_settimer\n");
                    139:        return -1;
                    140:     }
                    141:     node->func = action; 
                    142:     node->data = data;
                    143:     node->time = delay; 
                    144:     node->next = 0;    
                    145:     node->id   = ++id;
                    146:     
                    147:     prev = ptr = Q;
                    148:     
                    149:     /* insert node in the queue */
                    150:     
                    151:     /* if the queue is empty, insert the node and return */
                    152:     if (!Q)
                    153:        Q = node;
                    154:     else {
                    155:        /* chase the pointer looking for the right place */
                    156:        while (ptr) {
                    157:            
                    158:            if (delay < ptr->time) {
                    159:                /* right place */
                    160:                
                    161:                node->next = ptr;
                    162:                if (ptr == Q)
                    163:                    Q = node;
                    164:                else
                    165:                    prev->next = node;
                    166:                ptr->time -= node->time;
                    167:                print_Q();
                    168:                return node->id;
                    169:            } else  {
                    170:                /* keep moving */
                    171:                
                    172:                delay -= ptr->time; node->time = delay;
                    173:                prev = ptr;
                    174:                ptr = ptr->next;
                    175:            }
                    176:        }
                    177:        prev->next = node;
                    178:     }
                    179:     print_Q();
                    180:     return node->id;
                    181: }
                    182: 
                    183: /* returns the time until the timer is scheduled */
                    184: int
                    185: timer_leftTimer(timer_id)
                    186:     int timer_id;
                    187: {
                    188:     struct timeout_q *ptr;
                    189:     int left = 0;
                    190:        
                    191:     if (!timer_id)
                    192:        return -1;
                    193:     
                    194:     for (ptr = Q; ptr; ptr = ptr->next) {
                    195:        left += ptr->time;
                    196:        if (ptr->id == timer_id)
                    197:            return left;
                    198:     }
                    199:     return -1;
                    200: }
                    201: 
                    202: /* clears the associated timer */
                    203: void
                    204: timer_clearTimer(timer_id)
                    205:     int  timer_id;
                    206: {
                    207:     struct timeout_q  *ptr, *prev;
                    208:     
                    209:     if (!timer_id)
                    210:        return;
                    211:     
                    212:     prev = ptr = Q;
                    213:     
                    214:     /*
                    215:      * find the right node, delete it. the subsequent node's time
                    216:      * gets bumped up
                    217:      */
                    218:     
                    219:     print_Q();
                    220:     while (ptr) {
                    221:        if (ptr->id == timer_id) {
                    222:            /* got the right node */
                    223:            
                    224:            /* unlink it from the queue */
                    225:            if (ptr == Q)
                    226:                Q = Q->next;
                    227:            else
                    228:                prev->next = ptr->next;
                    229:            
                    230:            /* increment next node if any */
                    231:            if (ptr->next != 0)
                    232:                (ptr->next)->time += ptr->time;
                    233:            
                    234:            if (ptr->data)
                    235:                free(ptr->data);
                    236:            free(ptr);
                    237:            print_Q();
                    238:            return;
                    239:        }
                    240:        prev = ptr;
                    241:        ptr = ptr->next;
                    242:     }
                    243:     print_Q();
                    244: }
                    245: 
                    246: #ifdef CALLOUT_DEBUG2
                    247: /*
                    248:  * debugging utility
                    249:  */
                    250: static void
                    251: print_Q()
                    252: {
                    253:     struct timeout_q  *ptr;
                    254:     
                    255:     IF_DEBUG(DEBUG_TIMEOUT)
                    256:        for (ptr = Q; ptr; ptr = ptr->next)
                    257:            logit(LOG_DEBUG, 0, "(%d,%d) ", ptr->id, ptr->time);
                    258: }
                    259: #endif /* CALLOUT_DEBUG2 */
                    260: 
                    261: /**
                    262:  * Local Variables:
                    263:  *  version-control: t
                    264:  *  indent-tabs-mode: t
                    265:  *  c-file-style: "ellemtel"
                    266:  *  c-basic-offset: 4
                    267:  * End:
                    268:  */

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