Home | History | Annotate | Line # | Download | only in mrouted
callout.c revision 1.1
      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  * $Id: callout.c,v 1.1 1995/06/01 02:25:47 mycroft 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 static int in_callout= 0;
     20 
     21 typedef void (* cfunc_t)();
     22 
     23 struct timeout_q {
     24 	struct timeout_q *next;		/* next event */
     25 	int        	 id;
     26 	cfunc_t          func ;    	/* function to call */
     27 	char	   	 *data;		/* func's data */
     28 	int            	 time;		/* time offset to next event*/
     29 };
     30 
     31 static void print_Q();
     32 
     33 void callout_init()
     34 {
     35     Q = (struct timeout_q *) 0;
     36 }
     37 
     38 
     39 /*
     40  * signal handler for SIGALARM that is called once every second
     41  */
     42 void age_callout_queue()
     43 {
     44     struct timeout_q *ptr;
     45 
     46     if (in_callout)
     47 	return;
     48 
     49     in_callout = 1;
     50     ptr = Q;
     51 
     52     while (ptr){
     53 	if (!ptr->time ) {
     54 	    /* timeout has happened */
     55 	    if(ptr->func)
     56 		ptr->func(ptr->data);
     57 	    Q = Q->next;
     58 
     59 	    free(ptr);
     60 	    ptr = Q;
     61 	}
     62 	else {
     63 	    ptr->time --;
     64 #ifdef IGMP_DEBUG
     65 	    log(LOG_DEBUG,0,"[callout, age_callout_queue] -- time (%d)", ptr->time);
     66 #endif IGMP_DEBUG
     67 	    in_callout = 0; return;
     68 	}
     69     }
     70     in_callout = 0;
     71     return;
     72 }
     73 
     74 
     75 /*
     76  * sets the timer
     77  */
     78 int timer_setTimer(delay, action, data)
     79     int 	delay;  	/* number of units for timeout */
     80     cfunc_t	action; 	/* function to be called on timeout */
     81     char  	*data;  	/* what to call the timeout function with */
     82 {
     83     struct     timeout_q  *ptr, *node, *prev;
     84 
     85     if (in_callout)
     86 	return -1;
     87 
     88     in_callout = 1;
     89 
     90     /* create a node */
     91     node   = (struct timeout_q *)malloc(sizeof(struct timeout_q));
     92     if (node == 0) {
     93 	log(LOG_WARNING, 0, "Malloc Failed in timer_settimer\n");
     94 	in_callout = 0;
     95 	return -1;
     96     }
     97     node->func = action;
     98     node->data = data;
     99     node->time = delay;
    100     node->next = 0;
    101     node->id   = ++id;
    102 
    103     prev = ptr = Q;
    104 
    105     /* insert node in the queue */
    106 
    107     /* if the queue is empty, insert the node and return */
    108     if (!Q)
    109 	Q = node;
    110     else {
    111 	/* chase the pointer looking for the right place */
    112 	while (ptr){
    113 
    114 	    if (delay < ptr->time){
    115 		/* right place */
    116 
    117 		node->next = ptr;
    118 		if (ptr == Q)
    119 		    Q = node;
    120 		else
    121 		    prev->next = node;
    122 		ptr->time -= node->time;
    123 		print_Q();
    124 		in_callout = 0;
    125 		return node->id;
    126 	    }
    127 	    else  {
    128 		/* keep moving */
    129 
    130 		delay -= ptr->time; node->time = delay;
    131 		prev = ptr;
    132 		ptr = ptr->next;
    133 	    }
    134 	}
    135 	prev->next = node;
    136     }
    137     print_Q();
    138     in_callout = 0;
    139     return node->id;
    140 }
    141 
    142 
    143 /* clears the associated timer */
    144 void timer_clearTimer( timer_id)
    145     int  timer_id;
    146 {
    147     struct timeout_q  *ptr, *prev;
    148 
    149     if (in_callout)  return;
    150     in_callout = 1;
    151 
    152 
    153     if ( !timer_id ) {in_callout = 0; return;}
    154 
    155     prev = ptr = Q;
    156 
    157     /*
    158      * find the right node, delete it. the subsequent node's time
    159      * gets bumped up
    160      */
    161 
    162     print_Q();
    163     while (ptr){
    164 	if (ptr->id == timer_id){
    165 	    /* got the right node */
    166 
    167 	    /* unlink it from the queue */
    168 	    if ( ptr == Q)
    169 		Q = Q->next;
    170 	    else
    171 		prev->next = ptr->next;
    172 
    173 	    /* increment next node if any */
    174 	    if (ptr->next != 0)
    175 		(ptr->next)->time += ptr->time;
    176 
    177 	    free(ptr->data);
    178 	    free(ptr);
    179 	    print_Q();
    180 	    in_callout = 0;
    181 	    return;
    182 	}
    183 	prev = ptr;
    184 	ptr = ptr->next;
    185     }
    186     print_Q();
    187     in_callout = 0;
    188 }
    189 
    190 /*
    191  * debugging utility
    192  */
    193 static void print_Q()
    194 {
    195 #ifdef IGMP_DEBUG
    196     struct timeout_q  *ptr;
    197 
    198     for(ptr = Q; ptr; ptr = ptr->next)
    199 	log(LOG_DEBUG,0,"(%d,%d) ", ptr->id, ptr->time);
    200 #endif IGMP_DEBUG
    201 }
    202 
    203