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>