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