Return to schedule.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipsec-tools / src / racoon |
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