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

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