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>