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