Annotation of embedaddon/ipsec-tools/src/racoon/schedule.c, revision 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>