]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/pim6sd/callout.c
This commit was generated by cvs2svn to compensate for changes in r69833,
[FreeBSD/FreeBSD.git] / usr.sbin / pim6sd / 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 /*
13  *  Questions concerning this software should be directed to
14  *  Mickael Hoerdt (hoerdt@clarinet.u-strasbg.fr) LSIIT Strasbourg.
15  *
16  */
17 /*
18  * This program has been derived from pim6dd.
19  * The pim6dd program is covered by the license in the accompanying file
20  * named "LICENSE.pim6dd".
21  */
22 /*
23  * This program has been derived from pimd.
24  * The pimd program is covered by the license in the accompanying file
25  * named "LICENSE.pimd".
26  *
27  * $FreeBSD$
28  */
29
30
31 #include <stdio.h>
32 #include <syslog.h>
33 #include <stdlib.h>
34 #include "debug.h"
35 #include "defs.h"
36 #include "callout.h"
37
38 /* the code below implements a callout queue */
39
40 static int              id = 0;
41 static struct timeout_q *Q = 0; /* pointer to the beginning of timeout queue */
42
43 struct timeout_q
44 {
45     struct timeout_q *next;     /* next event */
46     int             id;
47     cfunc_t         func;       /* function to call */
48     void           *data;       /* func's data */
49     int             time;       /* time offset to next event */
50 };
51
52 #if 0
53 #define CALLOUT_DEBUG 1
54 #define CALLOUT_DEBUG2 1
55 #endif                          /* 0 */
56
57 #ifdef CALLOUT_DEBUG2
58 static void print_Q __P((void));
59 #else
60 #define print_Q()
61 #endif
62
63 void
64 callout_init()
65 {
66     Q = (struct timeout_q *) 0;
67 }
68
69 void
70 free_all_callouts()
71 {
72     struct timeout_q *p;
73
74     while (Q)
75     {
76         p = Q;
77         Q = Q->next;
78         free(p);
79     }
80 }
81
82
83 /*
84  * elapsed_time seconds have passed; perform all the events that should
85  * happen.
86  */
87 void
88 age_callout_queue(elapsed_time)
89     int             elapsed_time;
90 {
91     struct timeout_q *ptr,
92                    *expQ;
93
94 #ifdef CALLOUT_DEBUG
95     IF_DEBUG(DEBUG_TIMEOUT)
96         log(LOG_DEBUG, 0, "aging queue (elapsed time %d):", elapsed_time);
97     print_Q();
98 #endif
99
100     expQ = Q;
101     ptr = NULL;
102
103     while (Q)
104     {
105         if (Q->time > elapsed_time)
106         {
107             Q->time -= elapsed_time;
108             if (ptr)
109             {
110                 ptr->next = NULL;
111                 break;
112             }
113             return;
114         }
115         else
116         {
117             elapsed_time -= Q->time;
118             ptr = Q;
119             Q = Q->next;
120         }
121     }
122
123     /* handle queue of expired timers */
124     while (expQ)
125     {
126         ptr = expQ;
127         if (ptr->func)
128             ptr->func(ptr->data);
129         expQ = expQ->next;
130         free(ptr);
131     }
132 }
133
134 /*
135  * Return in how many seconds age_callout_queue() would like to be called.
136  * Return -1 if there are no events pending.
137  */
138
139 int
140 timer_nextTimer()
141 {
142     if (Q)
143     {
144         if (Q->time < 0)
145         {
146             log(LOG_WARNING, 0, "timer_nextTimer top of queue says %d",
147                 Q->time);
148             return 0;
149         }
150         return Q->time;
151     }
152     return -1;
153 }
154
155 /*
156  * sets the timer
157  */
158
159 int
160 timer_setTimer(delay, action, data)
161     int             delay;      /* number of units for timeout */
162     cfunc_t         action;     /* function to be called on timeout */
163     void           *data;       /* what to call the timeout function with */
164 {
165     struct timeout_q *ptr,
166                    *node,
167                    *prev;
168
169 #ifdef CALLOUT_DEBUG
170     IF_DEBUG(DEBUG_TIMEOUT)
171         log(LOG_DEBUG, 0, "setting timer:");
172     print_Q();
173 #endif
174
175     /* create a node */
176
177     node = (struct timeout_q *) malloc(sizeof(struct timeout_q));
178     if (node == 0)
179     {
180         log(LOG_WARNING, 0, "Malloc Failed in timer_settimer\n");
181         return -1;
182     }
183     node->func = action;
184     node->data = data;
185     node->time = delay;
186     node->next = 0;
187     node->id = ++id;
188
189     prev = ptr = Q;
190
191     /* insert node in the queue */
192
193     /* if the queue is empty, insert the node and return */
194
195     if (!Q)
196         Q = node;
197     else
198     {
199         /* chase the pointer looking for the right place */
200
201         while (ptr)
202         {
203
204             if (delay < ptr->time)
205             {
206                 /* right place */
207
208                 node->next = ptr;
209                 if (ptr == Q)
210                     Q = node;
211                 else
212                     prev->next = node;
213                 ptr->time -= node->time;
214                 print_Q();
215                 return node->id;
216             }
217             else
218             {
219                 /* keep moving */
220
221                 delay -= ptr->time;
222                 node->time = delay;
223                 prev = ptr;
224                 ptr = ptr->next;
225             }
226         }
227         prev->next = node;
228     }
229     print_Q();
230     return node->id;
231 }
232
233 /* returns the time until the timer is scheduled */
234
235 int
236 timer_leftTimer(timer_id)
237     int             timer_id;
238 {
239     struct timeout_q *ptr;
240     int             left = 0;
241
242     if (!timer_id)
243         return -1;
244
245     for (ptr = Q; ptr; ptr = ptr->next)
246     {
247         left += ptr->time;
248         if (ptr->id == timer_id)
249             return left;
250     }
251     return -1;
252 }
253
254 /* clears the associated timer */
255
256 void
257 timer_clearTimer(timer_id)
258     int             timer_id;
259 {
260     struct timeout_q *ptr,
261                    *prev;
262
263     if (!timer_id)
264         return;
265
266     prev = ptr = Q;
267
268     /*
269      * find the right node, delete it. the subsequent node's time gets bumped
270      * up
271      */
272
273     print_Q();
274     while (ptr)
275     {
276         if (ptr->id == timer_id)
277         {
278             /* got the right node */
279
280             /* unlink it from the queue */
281
282             if (ptr == Q)
283                 Q = Q->next;
284             else
285                 prev->next = ptr->next;
286
287             /* increment next node if any */
288             if (ptr->next != 0)
289                 (ptr->next)->time += ptr->time;
290
291             if (ptr->data)
292                 free(ptr->data);
293             free(ptr);
294             print_Q();
295             return;
296         }
297         prev = ptr;
298         ptr = ptr->next;
299     }
300     print_Q();
301 }
302
303 #ifdef CALLOUT_DEBUG2
304 /*
305  * debugging utility
306  */
307
308 static void
309 print_Q()
310 {
311     struct timeout_q *ptr;
312
313     IF_DEBUG(DEBUG_TIMEOUT)
314         for (ptr = Q; ptr; ptr = ptr->next)
315         log(LOG_DEBUG, 0, "(%d,%d) ", ptr->id, ptr->time);
316 }
317 #endif                          /* CALLOUT_DEBUG2 */