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