File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / pimd / callout.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jun 12 07:59:37 2017 UTC (6 years, 11 months ago) by misho
Branches: pimd, MAIN
CVS tags: v2_3_2, HEAD
pimd 2.3.2

    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>