]> git.saurik.com Git - apple/network_cmds.git/blob - racoon.tproj/schedule.c
7b4a2fb364909882470cd26aaddc961df1f41f8d
[apple/network_cmds.git] / racoon.tproj / schedule.c
1 /* $KAME: schedule.c,v 1.18 2001/10/08 23:58:22 sakane Exp $ */
2
3 /*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 #include <sys/types.h>
33 #include <sys/param.h>
34 #include <sys/time.h>
35 #include <sys/queue.h>
36
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <errno.h>
41
42 #include "misc.h"
43 #include "plog.h"
44 #include "schedule.h"
45 #include "var.h"
46 #include "gcmalloc.h"
47
48 #define FIXY2038PROBLEM
49
50 #ifndef TAILQ_FOREACH
51 #define TAILQ_FOREACH(elm, head, field) \
52 for (elm = TAILQ_FIRST(head); elm; elm = TAILQ_NEXT(elm, field))
53 #endif
54
55 static struct timeval timeout;
56
57 #ifdef FIXY2038PROBLEM
58 #define Y2038TIME_T 0x7fffffff
59 static time_t launched; /* time when the program launched. */
60 static time_t deltaY2038;
61 #endif
62
63 static TAILQ_HEAD(_schedtree, sched) sctree;
64
65 static void sched_add __P((struct sched *));
66 static time_t current_time __P((void));
67
68 /*
69 * schedule handler
70 * OUT:
71 * time to block until next event.
72 * if no entry, NULL returned.
73 */
74 struct timeval *
75 schedular()
76 {
77 time_t now, delta;
78 struct sched *p, *next = NULL;
79
80 now = current_time();
81
82 for (p = TAILQ_FIRST(&sctree); p; p = next) {
83 /* if the entry has been daed, remove it */
84 if (p->dead)
85 goto next_schedule;
86
87 /* if the time hasn't come, proceed to the next entry */
88 if (now < p->xtime) {
89 next = TAILQ_NEXT(p, chain);
90 continue;
91 }
92
93 /* mark it with dead. and call the function. */
94 p->dead = 1;
95 if (p->func != NULL)
96 (p->func)(p->param);
97
98 next_schedule:
99 next = TAILQ_NEXT(p, chain);
100 TAILQ_REMOVE(&sctree, p, chain);
101 racoon_free(p);
102 }
103
104 p = TAILQ_FIRST(&sctree);
105 if (p == NULL)
106 return NULL;
107
108 now = current_time();
109
110 delta = p->xtime - now;
111 timeout.tv_sec = delta < 0 ? 0 : delta;
112 timeout.tv_usec = 0;
113
114 return &timeout;
115 }
116
117 /*
118 * add new schedule to schedule table.
119 */
120 struct sched *
121 sched_new(tick, func, param)
122 time_t tick;
123 void (*func) __P((void *));
124 void *param;
125 {
126 static long id = 1;
127 struct sched *new;
128
129 new = (struct sched *)racoon_malloc(sizeof(*new));
130 if (new == NULL)
131 return NULL;
132
133 memset(new, 0, sizeof(*new));
134 new->func = func;
135 new->param = param;
136
137 new->id = id++;
138 time(&new->created);
139 new->tick = tick;
140
141 new->xtime = current_time() + tick;
142 new->dead = 0;
143
144 /* add to schedule table */
145 sched_add(new);
146
147 return(new);
148 }
149
150 /* add new schedule to schedule table */
151 static void
152 sched_add(sc)
153 struct sched *sc;
154 {
155 struct sched *p;
156
157 TAILQ_FOREACH(p, &sctree, chain) {
158 if (sc->xtime < p->xtime) {
159 TAILQ_INSERT_BEFORE(p, sc, chain);
160 return;
161 }
162 }
163 if (p == NULL)
164 TAILQ_INSERT_TAIL(&sctree, sc, chain);
165
166 return;
167 }
168
169 /* get current time.
170 * if defined FIXY2038PROBLEM, base time is the time when called sched_init().
171 * Otherwise, conform to time(3).
172 */
173 static time_t
174 current_time()
175 {
176 time_t n;
177 #ifdef FIXY2038PROBLEM
178 time_t t;
179
180 time(&n);
181 t = n - launched;
182 if (t < 0)
183 t += deltaY2038;
184
185 return t;
186 #else
187 return time(&n);
188 #endif
189 }
190
191 void
192 sched_kill(sc)
193 struct sched *sc;
194 {
195 sc->dead = 1;
196
197 return;
198 }
199
200 /* XXX this function is probably unnecessary. */
201 void
202 sched_scrub_param(param)
203 void *param;
204 {
205 struct sched *sc;
206
207 TAILQ_FOREACH(sc, &sctree, chain) {
208 if (sc->param == param) {
209 if (!sc->dead) {
210 plog(LLV_DEBUG, LOCATION, NULL,
211 "an undead schedule has been deleted.\n");
212 }
213 sched_kill(sc);
214 }
215 }
216 }
217
218 /*
219 * for debug
220 */
221 int
222 sched_dump(buf, len)
223 caddr_t *buf;
224 int *len;
225 {
226 caddr_t new;
227 struct sched *p;
228 struct scheddump *dst;
229 int cnt = 0;
230
231 /* initialize */
232 *len = 0;
233 *buf = NULL;
234
235 TAILQ_FOREACH(p, &sctree, chain)
236 cnt++;
237
238 /* no entry */
239 if (cnt == 0)
240 return -1;
241
242 *len = cnt * sizeof(*dst);
243
244 new = racoon_malloc(*len);
245 if (new == NULL)
246 return -1;
247 dst = (struct scheddump *)new;
248
249 p = TAILQ_FIRST(&sctree);
250 while (p) {
251 dst->xtime = p->xtime;
252 dst->id = p->id;
253 dst->created = p->created;
254 dst->tick = p->tick;
255
256 p = TAILQ_NEXT(p, chain);
257 if (p == NULL)
258 break;
259 dst++;
260 }
261
262 *buf = new;
263
264 return 0;
265 }
266
267 /* initialize schedule table */
268 void
269 sched_init()
270 {
271 #ifdef FIXY2038PROBLEM
272 time(&launched);
273
274 deltaY2038 = Y2038TIME_T - launched;
275 #endif
276
277 TAILQ_INIT(&sctree);
278
279 return;
280 }
281
282 #ifdef STEST
283 #include <sys/types.h>
284 #include <sys/time.h>
285 #include <unistd.h>
286 #include <err.h>
287
288 void
289 test(tick)
290 int *tick;
291 {
292 printf("execute %d\n", *tick);
293 racoon_free(tick);
294 }
295
296 void
297 getstdin()
298 {
299 int *tick;
300 char buf[16];
301
302 read(0, buf, sizeof(buf));
303 if (buf[0] == 'd') {
304 struct scheddump *scbuf, *p;
305 int len;
306 sched_dump((caddr_t *)&scbuf, &len);
307 if (buf == NULL)
308 return;
309 for (p = scbuf; len; p++) {
310 printf("xtime=%ld\n", p->xtime);
311 len -= sizeof(*p);
312 }
313 racoon_free(scbuf);
314 return;
315 }
316
317 tick = (int *)racoon_malloc(sizeof(*tick));
318 *tick = atoi(buf);
319 printf("new queue tick = %d\n", *tick);
320 sched_new(*tick, test, tick);
321 }
322
323 int
324 main()
325 {
326 static fd_set mask0;
327 int nfds = 0;
328 fd_set rfds;
329 struct timeval *timeout;
330 int error;
331
332 FD_ZERO(&mask0);
333 FD_SET(0, &mask0);
334 nfds = 1;
335
336 /* initialize */
337 sched_init();
338
339 while (1) {
340 rfds = mask0;
341
342 timeout = schedular();
343
344 error = select(nfds, &rfds, (fd_set *)0, (fd_set *)0, timeout);
345 if (error < 0) {
346 switch (errno) {
347 case EINTR: continue;
348 default:
349 err(1, "select");
350 }
351 /*NOTREACHED*/
352 }
353
354 if (FD_ISSET(0, &rfds))
355 getstdin();
356 }
357 }
358 #endif