Annotation of embedaddon/mrouted/callout.c, revision 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>