File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipsec-tools / src / racoon / schedule.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 22:39:10 2012 UTC (12 years, 4 months ago) by misho
Branches: ipsec-tools, MAIN
CVS tags: v0_8_2p2, v0_8_1p0, v0_8_1, v0_8_0p0, v0_8_0, HEAD
ipsec-tools

    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>