Annotation of embedaddon/ipsec-tools/src/racoon/schedule.c, revision 1.1.1.1
1.1 misho 1: /* $NetBSD: schedule.c,v 1.7 2009/01/23 09:10:13 tteras Exp $ */
2:
3: /* $KAME: schedule.c,v 1.19 2001/11/05 10:53:19 sakane Exp $ */
4:
5: /*
6: * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7: * Copyright (C) 2008 Timo Teras.
8: * All rights reserved.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. Neither the name of the project nor the names of its contributors
19: * may be used to endorse or promote products derived from this software
20: * without specific prior written permission.
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
23: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25: * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
26: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32: * SUCH DAMAGE.
33: */
34:
35: #include "config.h"
36:
37: #include <sys/types.h>
38: #include <sys/param.h>
39: #include <sys/time.h>
40: #include <sys/queue.h>
41: #include <sys/socket.h>
42:
43: #include <stdlib.h>
44: #include <unistd.h>
45: #include <stdio.h>
46: #include <string.h>
47: #include <errno.h>
48: #include <time.h>
49:
50: #include "misc.h"
51: #include "plog.h"
52: #include "schedule.h"
53: #include "var.h"
54: #include "gcmalloc.h"
55:
56: #ifndef TAILQ_FOREACH
57: #define TAILQ_FOREACH(elm, head, field) \
58: for (elm = TAILQ_FIRST(head); elm; elm = TAILQ_NEXT(elm, field))
59: #endif
60:
61: static TAILQ_HEAD(_schedtree, sched) sctree;
62:
63: void
64: sched_get_monotonic_time(tv)
65: struct timeval *tv;
66: {
67: #ifdef HAVE_CLOCK_MONOTONIC
68: struct timespec ts;
69:
70: clock_gettime(CLOCK_MONOTONIC, &ts);
71: tv->tv_sec = ts.tv_sec;
72: tv->tv_usec = ts.tv_nsec / 1000;
73: #else
74: gettimeofday(tv, NULL);
75: #endif
76: }
77:
78: time_t
79: sched_monotonic_to_time_t(tv, now)
80: struct timeval *tv, *now;
81: {
82: #ifdef HAVE_CLOCK_MONOTONIC
83: struct timeval mynow, res;
84:
85: if (now == NULL) {
86: sched_get_monotonic_time(&mynow);
87: now = &mynow;
88: }
89: timersub(now, tv, &res);
90:
91: return time(NULL) + res.tv_sec;
92: #else
93: return tv->tv_sec;
94: #endif
95: }
96:
97: /*
98: * schedule handler
99: * OUT:
100: * time to block until next event.
101: * if no entry, NULL returned.
102: */
103: struct timeval *
104: schedular()
105: {
106: static struct timeval timeout;
107: struct timeval now;
108: struct sched *p;
109:
110: sched_get_monotonic_time(&now);
111: while (!TAILQ_EMPTY(&sctree) &&
112: timercmp(&TAILQ_FIRST(&sctree)->xtime, &now, <=)) {
113: void (*func)(struct sched *);
114:
115: p = TAILQ_FIRST(&sctree);
116: func = p->func;
117: sched_cancel(p);
118: func(p);
119: }
120:
121: p = TAILQ_FIRST(&sctree);
122: if (p == NULL)
123: return NULL;
124:
125: timersub(&p->xtime, &now, &timeout);
126:
127: return &timeout;
128: }
129:
130: /*
131: * add new schedule to schedule table.
132: */
133: void
134: sched_schedule(sc, tick, func)
135: struct sched *sc;
136: time_t tick;
137: void (*func) __P((struct sched *));
138: {
139: static long id = 1;
140: struct sched *p;
141: struct timeval now;
142:
143: sched_cancel(sc);
144:
145: sc->func = func;
146: sc->id = id++;
147: sc->tick.tv_sec = tick;
148: sc->tick.tv_usec = 0;
149: sched_get_monotonic_time(&now);
150: timeradd(&now, &sc->tick, &sc->xtime);
151:
152: /* add to schedule table */
153: TAILQ_FOREACH(p, &sctree, chain) {
154: if (timercmp(&sc->xtime, &p->xtime, <))
155: break;
156: }
157: if (p == NULL)
158: TAILQ_INSERT_TAIL(&sctree, sc, chain);
159: else
160: TAILQ_INSERT_BEFORE(p, sc, chain);
161: }
162:
163: /*
164: * cancel scheduled callback
165: */
166: void
167: sched_cancel(sc)
168: struct sched *sc;
169: {
170: if (sc->func != NULL) {
171: TAILQ_REMOVE(&sctree, sc, chain);
172: sc->func = NULL;
173: }
174: }
175:
176: /*
177: * for debug
178: */
179: int
180: sched_dump(buf, len)
181: caddr_t *buf;
182: int *len;
183: {
184: caddr_t new;
185: struct sched *p;
186: struct scheddump *dst;
187: struct timeval now, created;
188: int cnt = 0;
189:
190: /* initialize */
191: *len = 0;
192: *buf = NULL;
193:
194: TAILQ_FOREACH(p, &sctree, chain)
195: cnt++;
196:
197: /* no entry */
198: if (cnt == 0)
199: return -1;
200:
201: *len = cnt * sizeof(*dst);
202:
203: new = racoon_malloc(*len);
204: if (new == NULL)
205: return -1;
206: dst = (struct scheddump *)new;
207:
208: sched_get_monotonic_time(&now);
209: p = TAILQ_FIRST(&sctree);
210: while (p) {
211: timersub(&p->xtime, &p->tick, &created);
212: dst->xtime = p->xtime.tv_sec;
213: dst->id = p->id;
214: dst->created = sched_monotonic_to_time_t(&created, &now);
215: dst->tick = p->tick.tv_sec;
216:
217: p = TAILQ_NEXT(p, chain);
218: if (p == NULL)
219: break;
220: dst++;
221: }
222:
223: *buf = new;
224:
225: return 0;
226: }
227:
228: /* initialize schedule table */
229: void
230: sched_init()
231: {
232: TAILQ_INIT(&sctree);
233: }
234:
235: #ifdef STEST
236: #include <sys/types.h>
237: #include <sys/time.h>
238: #include <unistd.h>
239: #include <err.h>
240:
241: void
242: test(tick)
243: int *tick;
244: {
245: printf("execute %d\n", *tick);
246: racoon_free(tick);
247: }
248:
249: void
250: getstdin()
251: {
252: int *tick;
253: char buf[16];
254:
255: read(0, buf, sizeof(buf));
256: if (buf[0] == 'd') {
257: struct scheddump *scbuf, *p;
258: int len;
259: sched_dump((caddr_t *)&scbuf, &len);
260: if (scbuf == NULL)
261: return;
262: for (p = scbuf; len; p++) {
263: printf("xtime=%ld\n", p->xtime);
264: len -= sizeof(*p);
265: }
266: racoon_free(scbuf);
267: return;
268: }
269:
270: tick = (int *)racoon_malloc(sizeof(*tick));
271: *tick = atoi(buf);
272: printf("new queue tick = %d\n", *tick);
273: sched_new(*tick, test, tick);
274: }
275:
276: int
277: main()
278: {
279: static fd_set mask0;
280: int nfds = 0;
281: fd_set rfds;
282: struct timeval *timeout;
283: int error;
284:
285: FD_ZERO(&mask0);
286: FD_SET(0, &mask0);
287: nfds = 1;
288:
289: /* initialize */
290: sched_init();
291:
292: while (1) {
293: rfds = mask0;
294:
295: timeout = schedular();
296:
297: error = select(nfds, &rfds, (fd_set *)0, (fd_set *)0, timeout);
298: if (error < 0) {
299: switch (errno) {
300: case EINTR: continue;
301: default:
302: err(1, "select");
303: }
304: /*NOTREACHED*/
305: }
306:
307: if (FD_ISSET(0, &rfds))
308: getstdin();
309: }
310: }
311: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>