]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/pim6dd/callout.c
This commit was generated by cvs2svn to compensate for changes in r71756,
[FreeBSD/FreeBSD.git] / usr.sbin / pim6dd / callout.c
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  * $FreeBSD$
13  */
14
15 #include "defs.h"
16
17 /* the code below implements a callout queue */
18 static int id = 0;
19 static struct timeout_q  *Q = 0; /* pointer to the beginning of timeout queue */
20
21 struct timeout_q {
22     struct timeout_q *next;             /* next event */
23     int              id;  
24     cfunc_t          func;              /* function to call */
25     void             *data;             /* func's data */
26     int              time;              /* time offset to next event*/
27 };
28
29 #ifdef CALLOUT_DEBUG
30 static void print_Q __P((void));
31 #else
32 #define print_Q()       
33 #endif
34
35 void
36 callout_init()
37 {
38     if (Q) {
39         log(LOG_ERR, 0, "timer used before callout_init()");
40         exit(1);
41     }
42     Q = (struct timeout_q *) 0;
43 }
44
45 void
46 free_all_callouts()
47 {
48     struct timeout_q *p;
49     
50     while (Q) {
51         p = Q;
52         Q = Q->next;
53         free(p);
54     }
55 }
56
57
58 /*
59  * elapsed_time seconds have passed; perform all the events that should
60  * happen.
61  */
62 void
63 age_callout_queue(elapsed_time)
64     int elapsed_time;
65 {
66     struct timeout_q *ptr, *expQ;
67     
68 #ifdef CALLOUT_DEBUG
69     IF_DEBUG(DEBUG_TIMEOUT)
70         log(LOG_DEBUG, 0, "aging queue (elapsed time %d):", elapsed_time);
71     print_Q();
72 #endif
73
74     expQ = Q;
75     ptr = NULL;
76     
77     while (Q) {
78         if (Q->time > elapsed_time) {
79             Q->time -= elapsed_time;
80             if (ptr) {
81                 ptr->next = NULL;
82                 break;
83             }
84             return;
85         } else {
86             elapsed_time -= Q->time;
87             ptr = Q;
88             Q = Q->next;
89         }
90     }
91     
92     /* handle queue of expired timers */
93     while (expQ) {
94         ptr = expQ;
95         if (ptr->func)
96             ptr->func(ptr->data);
97         expQ = expQ->next;
98         free(ptr);
99     }
100 }
101
102 /*
103  * Return in how many seconds age_callout_queue() would like to be called.
104  * Return -1 if there are no events pending.
105  */
106 int
107 timer_nextTimer()
108 {
109     if (Q) {
110         if (Q->time < 0) {
111             log(LOG_WARNING, 0, "timer_nextTimer top of queue says %d", 
112                 Q->time);
113             return 0;
114         }
115         return Q->time;
116     }
117     return -1;
118 }
119
120 /* 
121  * sets the timer
122  */
123 int
124 timer_setTimer(delay, action, data)
125     int         delay;          /* number of units for timeout */
126     cfunc_t     action;         /* function to be called on timeout */
127     void        *data;          /* what to call the timeout function with */
128 {
129     struct     timeout_q  *ptr, *node, *prev;
130     
131 #ifdef CALLOUT_DEBUG
132     IF_DEBUG(DEBUG_TIMEOUT)
133         log(LOG_DEBUG, 0, "setting timer:");
134     print_Q();
135 #endif
136
137     /* create a node */ 
138     node = (struct timeout_q *)malloc(sizeof(struct timeout_q));
139     if (node == 0) {
140         log(LOG_WARNING, 0, "Malloc Failed in timer_settimer\n");
141         return -1;
142     }
143     node->func = action; 
144     node->data = data;
145     node->time = delay; 
146     node->next = 0;     
147     node->id   = ++id;
148     
149     prev = ptr = Q;
150     
151     /* insert node in the queue */
152     
153     /* if the queue is empty, insert the node and return */
154     if (!Q)
155         Q = node;
156     else {
157         /* chase the pointer looking for the right place */
158         while (ptr) {
159             
160             if (delay < ptr->time) {
161                 /* right place */
162                 
163                 node->next = ptr;
164                 if (ptr == Q)
165                     Q = node;
166                 else
167                     prev->next = node;
168                 ptr->time -= node->time;
169                 return node->id;
170             } else  {
171                 /* keep moving */
172                 
173                 delay -= ptr->time; node->time = delay;
174                 prev = ptr;
175                 ptr = ptr->next;
176             }
177         }
178         prev->next = node;
179     }
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     while (ptr) {
220         if (ptr->id == timer_id) {
221             /* got the right node */
222             
223             /* unlink it from the queue */
224             if (ptr == Q)
225                 Q = Q->next;
226             else
227                 prev->next = ptr->next;
228             
229             /* increment next node if any */
230             if (ptr->next != 0)
231                 (ptr->next)->time += ptr->time;
232             
233             if (ptr->data)
234                 free(ptr->data);
235             free(ptr);
236             return;
237         }
238         prev = ptr;
239         ptr = ptr->next;
240     }
241 }
242
243 #ifdef CALLOUT_DEBUG
244 /*
245  * debugging utility
246  */
247 static void
248 print_Q()
249 {
250     struct timeout_q  *ptr;
251     
252     IF_DEBUG(DEBUG_TIMEOUT)
253         for (ptr = Q; ptr; ptr = ptr->next)
254             log(LOG_DEBUG, 0, "(%d,%d) ", ptr->id, ptr->time);
255 }
256 #endif /* CALLOUT_DEBUG */