Sweep-fix comparing pointers with 0 (and assigning 0 to pointers).
[games.git] / usr.sbin / mrouted / callout.c
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  * callout.c,v 3.8.4.8 1998/01/06 01:58:45 fenner Exp
11  *
12  * $FreeBSD: src/usr.sbin/mrouted/callout.c,v 1.12 1999/08/28 01:17:03 peter Exp $
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 = NULL; /* 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 IGMP_DEBUG
30 static void print_Q(void);
31 #else
32 #define print_Q()
33 #endif
34
35 void
36 callout_init(void)
37 {
38     Q = NULL;
39 }
40
41 void
42 free_all_callouts(void)
43 {
44     struct timeout_q *p;
45
46     while (Q) {
47         p = Q;
48         Q = Q->next;
49         free(p);
50     }
51 }
52
53
54 /*
55  * elapsed_time seconds have passed; perform all the events that should
56  * happen.
57  */
58 void
59 age_callout_queue(int elapsed_time)
60 {
61     struct timeout_q *ptr;
62     int i = 0;
63
64     for (ptr = Q; ptr; ptr = Q, i++) {
65         if (ptr->time > elapsed_time) {
66             ptr->time -= elapsed_time;
67             return;
68         } else {
69             elapsed_time -= ptr->time;
70             Q = Q->next;
71             IF_DEBUG(DEBUG_TIMEOUT)
72             dolog(LOG_DEBUG, 0, "about to call timeout %d (#%d)", ptr->id, i);
73             if (ptr->func)
74                 ptr->func(ptr->data);
75             free(ptr);
76         }
77     }
78 }
79
80 /*
81  * Return in how many seconds age_callout_queue() would like to be called.
82  * Return -1 if there are no events pending.
83  */
84 int
85 timer_nextTimer(void)
86 {
87     if (Q) {
88         if (Q->time < 0) {
89             dolog(LOG_WARNING, 0, "timer_nextTimer top of queue says %d",
90                         Q->time);
91             return 0;
92         }
93         return Q->time;
94     }
95     return -1;
96 }
97
98 /*
99  * sets the timer
100  *
101  * delay  - number of units for timeout
102  * action - function to be called on timeout
103  * data   - what to call the timeout function with
104  */
105 int
106 timer_setTimer(int delay, cfunc_t action, void *data)
107 {
108     struct     timeout_q  *ptr, *node, *prev;
109     int i = 0;
110
111     /* create a node */
112     node = (struct timeout_q *)malloc(sizeof(struct timeout_q));
113     if (node == NULL) {
114         dolog(LOG_WARNING, 0, "Malloc Failed in timer_setTimer\n");
115         return -1;
116     }
117     node->func = action;
118     node->data = data;
119     node->time = delay;
120     node->next = NULL;
121     node->id   = ++id;
122
123     prev = ptr = Q;
124
125     /* insert node in the queue */
126
127     /* if the queue is empty, insert the node and return */
128     if (!Q)
129         Q = node;
130     else {
131         /* chase the pointer looking for the right place */
132         while (ptr) {
133
134             if (delay < ptr->time) {
135                 /* right place */
136
137                 node->next = ptr;
138                 if (ptr == Q)
139                     Q = node;
140                 else
141                     prev->next = node;
142                 ptr->time -= node->time;
143                 print_Q();
144                 IF_DEBUG(DEBUG_TIMEOUT)
145                 dolog(LOG_DEBUG, 0, "created timeout %d (#%d)", node->id, i);
146                 return node->id;
147             } else  {
148                 /* keep moving */
149
150                 delay -= ptr->time; node->time = delay;
151                 prev = ptr;
152                 ptr = ptr->next;
153             }
154             i++;
155         }
156         prev->next = node;
157     }
158     print_Q();
159     IF_DEBUG(DEBUG_TIMEOUT)
160     dolog(LOG_DEBUG, 0, "created timeout %d (#%d)", node->id, i);
161     return node->id;
162 }
163
164 /* returns the time until the timer is scheduled */
165 int
166 timer_leftTimer(int timer_id)
167 {
168     struct timeout_q *ptr;
169     int left = 0;
170
171     if (!timer_id)
172         return -1;
173
174     for (ptr = Q; ptr; ptr = ptr->next) {
175         left += ptr->time;
176         if (ptr->id == timer_id)
177             return left;
178     }
179     return -1;
180 }
181
182 /* clears the associated timer.  Returns 1 if succeeded. */
183 int
184 timer_clearTimer(int timer_id)
185 {
186     struct timeout_q  *ptr, *prev;
187     int i = 0;
188
189     if (!timer_id)
190         return 0;
191
192     prev = ptr = Q;
193
194     /*
195      * find the right node, delete it. the subsequent node's time
196      * gets bumped up
197      */
198
199     print_Q();
200     while (ptr) {
201         if (ptr->id == timer_id) {
202             /* got the right node */
203
204             /* unlink it from the queue */
205             if (ptr == Q)
206                 Q = Q->next;
207             else
208                 prev->next = ptr->next;
209
210             /* increment next node if any */
211             if (ptr->next != NULL)
212                 (ptr->next)->time += ptr->time;
213
214             if (ptr->data)
215                 free(ptr->data);
216             IF_DEBUG(DEBUG_TIMEOUT)
217             dolog(LOG_DEBUG, 0, "deleted timer %d (#%d)", ptr->id, i);
218             free(ptr);
219             print_Q();
220             return 1;
221         }
222         prev = ptr;
223         ptr = ptr->next;
224         i++;
225     }
226     IF_DEBUG(DEBUG_TIMEOUT)
227     dolog(LOG_DEBUG, 0, "failed to delete timer %d (#%d)", timer_id, i);
228     print_Q();
229     return 0;
230 }
231
232 #ifdef IGMP_DEBUG
233 /*
234  * debugging utility
235  */
236 static void
237 print_Q(void)
238 {
239     struct timeout_q  *ptr;
240
241     IF_DEBUG(DEBUG_TIMEOUT)
242         for (ptr = Q; ptr; ptr = ptr->next)
243             dolog(LOG_DEBUG, 0, "(%d,%d) ", ptr->id, ptr->time);
244 }
245 #endif /* IGMP_DEBUG */