File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mrouted / callout.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 23:10:48 2012 UTC (12 years, 3 months ago) by misho
Branches: mrouted, MAIN
CVS tags: v3_9_6p0, v3_9_6, v3_9_5, HEAD
mrouted

    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>