Annotation of embedaddon/libevent/event.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (c) 2000-2004 Niels Provos <provos@citi.umich.edu>
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  * 3. The name of the author may not be used to endorse or promote products
                     14:  *    derived from this software without specific prior written permission.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     17:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     18:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     19:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     20:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     21:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     22:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     23:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     24:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     25:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     26:  */
                     27: #ifdef HAVE_CONFIG_H
                     28: #include "config.h"
                     29: #endif
                     30: 
                     31: #ifdef WIN32
                     32: #define WIN32_LEAN_AND_MEAN
                     33: #include <windows.h>
                     34: #undef WIN32_LEAN_AND_MEAN
                     35: #endif
                     36: #include <sys/types.h>
                     37: #ifdef HAVE_SYS_TIME_H
                     38: #include <sys/time.h>
                     39: #else 
                     40: #include <sys/_libevent_time.h>
                     41: #endif
                     42: #include <sys/queue.h>
                     43: #include <stdio.h>
                     44: #include <stdlib.h>
                     45: #ifndef WIN32
                     46: #include <unistd.h>
                     47: #endif
                     48: #include <errno.h>
                     49: #include <signal.h>
                     50: #include <string.h>
                     51: #include <assert.h>
                     52: #include <time.h>
                     53: 
                     54: #include "event.h"
                     55: #include "event-internal.h"
                     56: #include "evutil.h"
                     57: #include "log.h"
                     58: 
                     59: #ifdef HAVE_EVENT_PORTS
                     60: extern const struct eventop evportops;
                     61: #endif
                     62: #ifdef HAVE_SELECT
                     63: extern const struct eventop selectops;
                     64: #endif
                     65: #ifdef HAVE_POLL
                     66: extern const struct eventop pollops;
                     67: #endif
                     68: #ifdef HAVE_EPOLL
                     69: extern const struct eventop epollops;
                     70: #endif
                     71: #ifdef HAVE_WORKING_KQUEUE
                     72: extern const struct eventop kqops;
                     73: #endif
                     74: #ifdef HAVE_DEVPOLL
                     75: extern const struct eventop devpollops;
                     76: #endif
                     77: #ifdef WIN32
                     78: extern const struct eventop win32ops;
                     79: #endif
                     80: 
                     81: /* In order of preference */
                     82: static const struct eventop *eventops[] = {
                     83: #ifdef HAVE_EVENT_PORTS
                     84:        &evportops,
                     85: #endif
                     86: #ifdef HAVE_WORKING_KQUEUE
                     87:        &kqops,
                     88: #endif
                     89: #ifdef HAVE_EPOLL
                     90:        &epollops,
                     91: #endif
                     92: #ifdef HAVE_DEVPOLL
                     93:        &devpollops,
                     94: #endif
                     95: #ifdef HAVE_POLL
                     96:        &pollops,
                     97: #endif
                     98: #ifdef HAVE_SELECT
                     99:        &selectops,
                    100: #endif
                    101: #ifdef WIN32
                    102:        &win32ops,
                    103: #endif
                    104:        NULL
                    105: };
                    106: 
                    107: /* Global state */
                    108: struct event_base *current_base = NULL;
                    109: extern struct event_base *evsignal_base;
                    110: static int use_monotonic;
                    111: 
                    112: /* Handle signals - This is a deprecated interface */
                    113: int (*event_sigcb)(void);              /* Signal callback when gotsig is set */
                    114: volatile sig_atomic_t event_gotsig;    /* Set in signal handler */
                    115: 
                    116: /* Prototypes */
                    117: static void    event_queue_insert(struct event_base *, struct event *, int);
                    118: static void    event_queue_remove(struct event_base *, struct event *, int);
                    119: static int     event_haveevents(struct event_base *);
                    120: 
                    121: static void    event_process_active(struct event_base *);
                    122: 
                    123: static int     timeout_next(struct event_base *, struct timeval **);
                    124: static void    timeout_process(struct event_base *);
                    125: static void    timeout_correct(struct event_base *, struct timeval *);
                    126: 
                    127: static void
                    128: detect_monotonic(void)
                    129: {
                    130: #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
                    131:        struct timespec ts;
                    132: 
                    133:        if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
                    134:                use_monotonic = 1;
                    135: #endif
                    136: }
                    137: 
                    138: static int
                    139: gettime(struct event_base *base, struct timeval *tp)
                    140: {
                    141:        if (base->tv_cache.tv_sec) {
                    142:                *tp = base->tv_cache;
                    143:                return (0);
                    144:        }
                    145: 
                    146: #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
                    147:        if (use_monotonic) {
                    148:                struct timespec ts;
                    149: 
                    150:                if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
                    151:                        return (-1);
                    152: 
                    153:                tp->tv_sec = ts.tv_sec;
                    154:                tp->tv_usec = ts.tv_nsec / 1000;
                    155:                return (0);
                    156:        }
                    157: #endif
                    158: 
                    159:        return (evutil_gettimeofday(tp, NULL));
                    160: }
                    161: 
                    162: struct event_base *
                    163: event_init(void)
                    164: {
                    165:        struct event_base *base = event_base_new();
                    166: 
                    167:        if (base != NULL)
                    168:                current_base = base;
                    169: 
                    170:        return (base);
                    171: }
                    172: 
                    173: struct event_base *
                    174: event_base_new(void)
                    175: {
                    176:        int i;
                    177:        struct event_base *base;
                    178: 
                    179:        if ((base = calloc(1, sizeof(struct event_base))) == NULL)
                    180:                event_err(1, "%s: calloc", __func__);
                    181: 
                    182:        event_sigcb = NULL;
                    183:        event_gotsig = 0;
                    184: 
                    185:        detect_monotonic();
                    186:        gettime(base, &base->event_tv);
                    187:        
                    188:        min_heap_ctor(&base->timeheap);
                    189:        TAILQ_INIT(&base->eventqueue);
                    190:        base->sig.ev_signal_pair[0] = -1;
                    191:        base->sig.ev_signal_pair[1] = -1;
                    192:        
                    193:        base->evbase = NULL;
                    194:        for (i = 0; eventops[i] && !base->evbase; i++) {
                    195:                base->evsel = eventops[i];
                    196: 
                    197:                base->evbase = base->evsel->init(base);
                    198:        }
                    199: 
                    200:        if (base->evbase == NULL)
                    201:                event_errx(1, "%s: no event mechanism available", __func__);
                    202: 
                    203:        if (evutil_getenv("EVENT_SHOW_METHOD")) 
                    204:                event_msgx("libevent using: %s\n",
                    205:                           base->evsel->name);
                    206: 
                    207:        /* allocate a single active event queue */
                    208:        event_base_priority_init(base, 1);
                    209: 
                    210:        return (base);
                    211: }
                    212: 
                    213: void
                    214: event_base_free(struct event_base *base)
                    215: {
                    216:        int i, n_deleted=0;
                    217:        struct event *ev;
                    218: 
                    219:        if (base == NULL && current_base)
                    220:                base = current_base;
                    221:        if (base == current_base)
                    222:                current_base = NULL;
                    223: 
                    224:        /* XXX(niels) - check for internal events first */
                    225:        assert(base);
                    226:        /* Delete all non-internal events. */
                    227:        for (ev = TAILQ_FIRST(&base->eventqueue); ev; ) {
                    228:                struct event *next = TAILQ_NEXT(ev, ev_next);
                    229:                if (!(ev->ev_flags & EVLIST_INTERNAL)) {
                    230:                        event_del(ev);
                    231:                        ++n_deleted;
                    232:                }
                    233:                ev = next;
                    234:        }
                    235:        while ((ev = min_heap_top(&base->timeheap)) != NULL) {
                    236:                event_del(ev);
                    237:                ++n_deleted;
                    238:        }
                    239: 
                    240:        for (i = 0; i < base->nactivequeues; ++i) {
                    241:                for (ev = TAILQ_FIRST(base->activequeues[i]); ev; ) {
                    242:                        struct event *next = TAILQ_NEXT(ev, ev_active_next);
                    243:                        if (!(ev->ev_flags & EVLIST_INTERNAL)) {
                    244:                                event_del(ev);
                    245:                                ++n_deleted;
                    246:                        }
                    247:                        ev = next;
                    248:                }
                    249:        }
                    250: 
                    251:        if (n_deleted)
                    252:                event_debug(("%s: %d events were still set in base",
                    253:                        __func__, n_deleted));
                    254: 
                    255:        if (base->evsel->dealloc != NULL)
                    256:                base->evsel->dealloc(base, base->evbase);
                    257: 
                    258:        for (i = 0; i < base->nactivequeues; ++i)
                    259:                assert(TAILQ_EMPTY(base->activequeues[i]));
                    260: 
                    261:        assert(min_heap_empty(&base->timeheap));
                    262:        min_heap_dtor(&base->timeheap);
                    263: 
                    264:        for (i = 0; i < base->nactivequeues; ++i)
                    265:                free(base->activequeues[i]);
                    266:        free(base->activequeues);
                    267: 
                    268:        assert(TAILQ_EMPTY(&base->eventqueue));
                    269: 
                    270:        free(base);
                    271: }
                    272: 
                    273: /* reinitialized the event base after a fork */
                    274: int
                    275: event_reinit(struct event_base *base)
                    276: {
                    277:        const struct eventop *evsel = base->evsel;
                    278:        void *evbase = base->evbase;
                    279:        int res = 0;
                    280:        struct event *ev;
                    281: 
                    282:        /* check if this event mechanism requires reinit */
                    283:        if (!evsel->need_reinit)
                    284:                return (0);
                    285: 
                    286:        /* prevent internal delete */
                    287:        if (base->sig.ev_signal_added) {
                    288:                /* we cannot call event_del here because the base has
                    289:                 * not been reinitialized yet. */
                    290:                event_queue_remove(base, &base->sig.ev_signal,
                    291:                    EVLIST_INSERTED);
                    292:                if (base->sig.ev_signal.ev_flags & EVLIST_ACTIVE)
                    293:                        event_queue_remove(base, &base->sig.ev_signal,
                    294:                            EVLIST_ACTIVE);
                    295:                base->sig.ev_signal_added = 0;
                    296:        }
                    297:        
                    298:        if (base->evsel->dealloc != NULL)
                    299:                base->evsel->dealloc(base, base->evbase);
                    300:        evbase = base->evbase = evsel->init(base);
                    301:        if (base->evbase == NULL)
                    302:                event_errx(1, "%s: could not reinitialize event mechanism",
                    303:                    __func__);
                    304: 
                    305:        TAILQ_FOREACH(ev, &base->eventqueue, ev_next) {
                    306:                if (evsel->add(evbase, ev) == -1)
                    307:                        res = -1;
                    308:        }
                    309: 
                    310:        return (res);
                    311: }
                    312: 
                    313: int
                    314: event_priority_init(int npriorities)
                    315: {
                    316:   return event_base_priority_init(current_base, npriorities);
                    317: }
                    318: 
                    319: int
                    320: event_base_priority_init(struct event_base *base, int npriorities)
                    321: {
                    322:        int i;
                    323: 
                    324:        if (base->event_count_active)
                    325:                return (-1);
                    326: 
                    327:        if (npriorities == base->nactivequeues)
                    328:                return (0);
                    329: 
                    330:        if (base->nactivequeues) {
                    331:                for (i = 0; i < base->nactivequeues; ++i) {
                    332:                        free(base->activequeues[i]);
                    333:                }
                    334:                free(base->activequeues);
                    335:        }
                    336: 
                    337:        /* Allocate our priority queues */
                    338:        base->nactivequeues = npriorities;
                    339:        base->activequeues = (struct event_list **)
                    340:            calloc(base->nactivequeues, sizeof(struct event_list *));
                    341:        if (base->activequeues == NULL)
                    342:                event_err(1, "%s: calloc", __func__);
                    343: 
                    344:        for (i = 0; i < base->nactivequeues; ++i) {
                    345:                base->activequeues[i] = malloc(sizeof(struct event_list));
                    346:                if (base->activequeues[i] == NULL)
                    347:                        event_err(1, "%s: malloc", __func__);
                    348:                TAILQ_INIT(base->activequeues[i]);
                    349:        }
                    350: 
                    351:        return (0);
                    352: }
                    353: 
                    354: int
                    355: event_haveevents(struct event_base *base)
                    356: {
                    357:        return (base->event_count > 0);
                    358: }
                    359: 
                    360: /*
                    361:  * Active events are stored in priority queues.  Lower priorities are always
                    362:  * process before higher priorities.  Low priority events can starve high
                    363:  * priority ones.
                    364:  */
                    365: 
                    366: static void
                    367: event_process_active(struct event_base *base)
                    368: {
                    369:        struct event *ev;
                    370:        struct event_list *activeq = NULL;
                    371:        int i;
                    372:        short ncalls;
                    373: 
                    374:        for (i = 0; i < base->nactivequeues; ++i) {
                    375:                if (TAILQ_FIRST(base->activequeues[i]) != NULL) {
                    376:                        activeq = base->activequeues[i];
                    377:                        break;
                    378:                }
                    379:        }
                    380: 
                    381:        assert(activeq != NULL);
                    382: 
                    383:        for (ev = TAILQ_FIRST(activeq); ev; ev = TAILQ_FIRST(activeq)) {
                    384:                if (ev->ev_events & EV_PERSIST)
                    385:                        event_queue_remove(base, ev, EVLIST_ACTIVE);
                    386:                else
                    387:                        event_del(ev);
                    388:                
                    389:                /* Allows deletes to work */
                    390:                ncalls = ev->ev_ncalls;
                    391:                ev->ev_pncalls = &ncalls;
                    392:                while (ncalls) {
                    393:                        ncalls--;
                    394:                        ev->ev_ncalls = ncalls;
                    395:                        (*ev->ev_callback)((int)ev->ev_fd, ev->ev_res, ev->ev_arg);
                    396:                        if (event_gotsig || base->event_break)
                    397:                                return;
                    398:                }
                    399:        }
                    400: }
                    401: 
                    402: /*
                    403:  * Wait continously for events.  We exit only if no events are left.
                    404:  */
                    405: 
                    406: int
                    407: event_dispatch(void)
                    408: {
                    409:        return (event_loop(0));
                    410: }
                    411: 
                    412: int
                    413: event_base_dispatch(struct event_base *event_base)
                    414: {
                    415:   return (event_base_loop(event_base, 0));
                    416: }
                    417: 
                    418: const char *
                    419: event_base_get_method(struct event_base *base)
                    420: {
                    421:        assert(base);
                    422:        return (base->evsel->name);
                    423: }
                    424: 
                    425: static void
                    426: event_loopexit_cb(int fd, short what, void *arg)
                    427: {
                    428:        struct event_base *base = arg;
                    429:        base->event_gotterm = 1;
                    430: }
                    431: 
                    432: /* not thread safe */
                    433: int
                    434: event_loopexit(const struct timeval *tv)
                    435: {
                    436:        return (event_once(-1, EV_TIMEOUT, event_loopexit_cb,
                    437:                    current_base, tv));
                    438: }
                    439: 
                    440: int
                    441: event_base_loopexit(struct event_base *event_base, const struct timeval *tv)
                    442: {
                    443:        return (event_base_once(event_base, -1, EV_TIMEOUT, event_loopexit_cb,
                    444:                    event_base, tv));
                    445: }
                    446: 
                    447: /* not thread safe */
                    448: int
                    449: event_loopbreak(void)
                    450: {
                    451:        return (event_base_loopbreak(current_base));
                    452: }
                    453: 
                    454: int
                    455: event_base_loopbreak(struct event_base *event_base)
                    456: {
                    457:        if (event_base == NULL)
                    458:                return (-1);
                    459: 
                    460:        event_base->event_break = 1;
                    461:        return (0);
                    462: }
                    463: 
                    464: 
                    465: 
                    466: /* not thread safe */
                    467: 
                    468: int
                    469: event_loop(int flags)
                    470: {
                    471:        return event_base_loop(current_base, flags);
                    472: }
                    473: 
                    474: int
                    475: event_base_loop(struct event_base *base, int flags)
                    476: {
                    477:        const struct eventop *evsel = base->evsel;
                    478:        void *evbase = base->evbase;
                    479:        struct timeval tv;
                    480:        struct timeval *tv_p;
                    481:        int res, done;
                    482: 
                    483:        /* clear time cache */
                    484:        base->tv_cache.tv_sec = 0;
                    485: 
                    486:        if (base->sig.ev_signal_added)
                    487:                evsignal_base = base;
                    488:        done = 0;
                    489:        while (!done) {
                    490:                /* Terminate the loop if we have been asked to */
                    491:                if (base->event_gotterm) {
                    492:                        base->event_gotterm = 0;
                    493:                        break;
                    494:                }
                    495: 
                    496:                if (base->event_break) {
                    497:                        base->event_break = 0;
                    498:                        break;
                    499:                }
                    500: 
                    501:                /* You cannot use this interface for multi-threaded apps */
                    502:                while (event_gotsig) {
                    503:                        event_gotsig = 0;
                    504:                        if (event_sigcb) {
                    505:                                res = (*event_sigcb)();
                    506:                                if (res == -1) {
                    507:                                        errno = EINTR;
                    508:                                        return (-1);
                    509:                                }
                    510:                        }
                    511:                }
                    512: 
                    513:                timeout_correct(base, &tv);
                    514: 
                    515:                tv_p = &tv;
                    516:                if (!base->event_count_active && !(flags & EVLOOP_NONBLOCK)) {
                    517:                        timeout_next(base, &tv_p);
                    518:                } else {
                    519:                        /* 
                    520:                         * if we have active events, we just poll new events
                    521:                         * without waiting.
                    522:                         */
                    523:                        evutil_timerclear(&tv);
                    524:                }
                    525:                
                    526:                /* If we have no events, we just exit */
                    527:                if (!event_haveevents(base)) {
                    528:                        event_debug(("%s: no events registered.", __func__));
                    529:                        return (1);
                    530:                }
                    531: 
                    532:                /* update last old time */
                    533:                gettime(base, &base->event_tv);
                    534: 
                    535:                /* clear time cache */
                    536:                base->tv_cache.tv_sec = 0;
                    537: 
                    538:                res = evsel->dispatch(base, evbase, tv_p);
                    539: 
                    540:                if (res == -1)
                    541:                        return (-1);
                    542:                gettime(base, &base->tv_cache);
                    543: 
                    544:                timeout_process(base);
                    545: 
                    546:                if (base->event_count_active) {
                    547:                        event_process_active(base);
                    548:                        if (!base->event_count_active && (flags & EVLOOP_ONCE))
                    549:                                done = 1;
                    550:                } else if (flags & EVLOOP_NONBLOCK)
                    551:                        done = 1;
                    552:        }
                    553: 
                    554:        /* clear time cache */
                    555:        base->tv_cache.tv_sec = 0;
                    556: 
                    557:        event_debug(("%s: asked to terminate loop.", __func__));
                    558:        return (0);
                    559: }
                    560: 
                    561: /* Sets up an event for processing once */
                    562: 
                    563: struct event_once {
                    564:        struct event ev;
                    565: 
                    566:        void (*cb)(int, short, void *);
                    567:        void *arg;
                    568: };
                    569: 
                    570: /* One-time callback, it deletes itself */
                    571: 
                    572: static void
                    573: event_once_cb(int fd, short events, void *arg)
                    574: {
                    575:        struct event_once *eonce = arg;
                    576: 
                    577:        (*eonce->cb)(fd, events, eonce->arg);
                    578:        free(eonce);
                    579: }
                    580: 
                    581: /* not threadsafe, event scheduled once. */
                    582: int
                    583: event_once(int fd, short events,
                    584:     void (*callback)(int, short, void *), void *arg, const struct timeval *tv)
                    585: {
                    586:        return event_base_once(current_base, fd, events, callback, arg, tv);
                    587: }
                    588: 
                    589: /* Schedules an event once */
                    590: int
                    591: event_base_once(struct event_base *base, int fd, short events,
                    592:     void (*callback)(int, short, void *), void *arg, const struct timeval *tv)
                    593: {
                    594:        struct event_once *eonce;
                    595:        struct timeval etv;
                    596:        int res;
                    597: 
                    598:        /* We cannot support signals that just fire once */
                    599:        if (events & EV_SIGNAL)
                    600:                return (-1);
                    601: 
                    602:        if ((eonce = calloc(1, sizeof(struct event_once))) == NULL)
                    603:                return (-1);
                    604: 
                    605:        eonce->cb = callback;
                    606:        eonce->arg = arg;
                    607: 
                    608:        if (events == EV_TIMEOUT) {
                    609:                if (tv == NULL) {
                    610:                        evutil_timerclear(&etv);
                    611:                        tv = &etv;
                    612:                }
                    613: 
                    614:                evtimer_set(&eonce->ev, event_once_cb, eonce);
                    615:        } else if (events & (EV_READ|EV_WRITE)) {
                    616:                events &= EV_READ|EV_WRITE;
                    617: 
                    618:                event_set(&eonce->ev, fd, events, event_once_cb, eonce);
                    619:        } else {
                    620:                /* Bad event combination */
                    621:                free(eonce);
                    622:                return (-1);
                    623:        }
                    624: 
                    625:        res = event_base_set(base, &eonce->ev);
                    626:        if (res == 0)
                    627:                res = event_add(&eonce->ev, tv);
                    628:        if (res != 0) {
                    629:                free(eonce);
                    630:                return (res);
                    631:        }
                    632: 
                    633:        return (0);
                    634: }
                    635: 
                    636: void
                    637: event_set(struct event *ev, int fd, short events,
                    638:          void (*callback)(int, short, void *), void *arg)
                    639: {
                    640:        /* Take the current base - caller needs to set the real base later */
                    641:        ev->ev_base = current_base;
                    642: 
                    643:        ev->ev_callback = callback;
                    644:        ev->ev_arg = arg;
                    645:        ev->ev_fd = fd;
                    646:        ev->ev_events = events;
                    647:        ev->ev_res = 0;
                    648:        ev->ev_flags = EVLIST_INIT;
                    649:        ev->ev_ncalls = 0;
                    650:        ev->ev_pncalls = NULL;
                    651: 
                    652:        min_heap_elem_init(ev);
                    653: 
                    654:        /* by default, we put new events into the middle priority */
                    655:        if(current_base)
                    656:                ev->ev_pri = current_base->nactivequeues/2;
                    657: }
                    658: 
                    659: int
                    660: event_base_set(struct event_base *base, struct event *ev)
                    661: {
                    662:        /* Only innocent events may be assigned to a different base */
                    663:        if (ev->ev_flags != EVLIST_INIT)
                    664:                return (-1);
                    665: 
                    666:        ev->ev_base = base;
                    667:        ev->ev_pri = base->nactivequeues/2;
                    668: 
                    669:        return (0);
                    670: }
                    671: 
                    672: /*
                    673:  * Set's the priority of an event - if an event is already scheduled
                    674:  * changing the priority is going to fail.
                    675:  */
                    676: 
                    677: int
                    678: event_priority_set(struct event *ev, int pri)
                    679: {
                    680:        if (ev->ev_flags & EVLIST_ACTIVE)
                    681:                return (-1);
                    682:        if (pri < 0 || pri >= ev->ev_base->nactivequeues)
                    683:                return (-1);
                    684: 
                    685:        ev->ev_pri = pri;
                    686: 
                    687:        return (0);
                    688: }
                    689: 
                    690: /*
                    691:  * Checks if a specific event is pending or scheduled.
                    692:  */
                    693: 
                    694: int
                    695: event_pending(struct event *ev, short event, struct timeval *tv)
                    696: {
                    697:        struct timeval  now, res;
                    698:        int flags = 0;
                    699: 
                    700:        if (ev->ev_flags & EVLIST_INSERTED)
                    701:                flags |= (ev->ev_events & (EV_READ|EV_WRITE|EV_SIGNAL));
                    702:        if (ev->ev_flags & EVLIST_ACTIVE)
                    703:                flags |= ev->ev_res;
                    704:        if (ev->ev_flags & EVLIST_TIMEOUT)
                    705:                flags |= EV_TIMEOUT;
                    706: 
                    707:        event &= (EV_TIMEOUT|EV_READ|EV_WRITE|EV_SIGNAL);
                    708: 
                    709:        /* See if there is a timeout that we should report */
                    710:        if (tv != NULL && (flags & event & EV_TIMEOUT)) {
                    711:                gettime(ev->ev_base, &now);
                    712:                evutil_timersub(&ev->ev_timeout, &now, &res);
                    713:                /* correctly remap to real time */
                    714:                evutil_gettimeofday(&now, NULL);
                    715:                evutil_timeradd(&now, &res, tv);
                    716:        }
                    717: 
                    718:        return (flags & event);
                    719: }
                    720: 
                    721: int
                    722: event_add(struct event *ev, const struct timeval *tv)
                    723: {
                    724:        struct event_base *base = ev->ev_base;
                    725:        const struct eventop *evsel = base->evsel;
                    726:        void *evbase = base->evbase;
                    727:        int res = 0;
                    728: 
                    729:        event_debug((
                    730:                 "event_add: event: %p, %s%s%scall %p",
                    731:                 ev,
                    732:                 ev->ev_events & EV_READ ? "EV_READ " : " ",
                    733:                 ev->ev_events & EV_WRITE ? "EV_WRITE " : " ",
                    734:                 tv ? "EV_TIMEOUT " : " ",
                    735:                 ev->ev_callback));
                    736: 
                    737:        assert(!(ev->ev_flags & ~EVLIST_ALL));
                    738: 
                    739:        /*
                    740:         * prepare for timeout insertion further below, if we get a
                    741:         * failure on any step, we should not change any state.
                    742:         */
                    743:        if (tv != NULL && !(ev->ev_flags & EVLIST_TIMEOUT)) {
                    744:                if (min_heap_reserve(&base->timeheap,
                    745:                        1 + min_heap_size(&base->timeheap)) == -1)
                    746:                        return (-1);  /* ENOMEM == errno */
                    747:        }
                    748: 
                    749:        if ((ev->ev_events & (EV_READ|EV_WRITE|EV_SIGNAL)) &&
                    750:            !(ev->ev_flags & (EVLIST_INSERTED|EVLIST_ACTIVE))) {
                    751:                res = evsel->add(evbase, ev);
                    752:                if (res != -1)
                    753:                        event_queue_insert(base, ev, EVLIST_INSERTED);
                    754:        }
                    755: 
                    756:        /* 
                    757:         * we should change the timout state only if the previous event
                    758:         * addition succeeded.
                    759:         */
                    760:        if (res != -1 && tv != NULL) {
                    761:                struct timeval now;
                    762: 
                    763:                /* 
                    764:                 * we already reserved memory above for the case where we
                    765:                 * are not replacing an exisiting timeout.
                    766:                 */
                    767:                if (ev->ev_flags & EVLIST_TIMEOUT)
                    768:                        event_queue_remove(base, ev, EVLIST_TIMEOUT);
                    769: 
                    770:                /* Check if it is active due to a timeout.  Rescheduling
                    771:                 * this timeout before the callback can be executed
                    772:                 * removes it from the active list. */
                    773:                if ((ev->ev_flags & EVLIST_ACTIVE) &&
                    774:                    (ev->ev_res & EV_TIMEOUT)) {
                    775:                        /* See if we are just active executing this
                    776:                         * event in a loop
                    777:                         */
                    778:                        if (ev->ev_ncalls && ev->ev_pncalls) {
                    779:                                /* Abort loop */
                    780:                                *ev->ev_pncalls = 0;
                    781:                        }
                    782:                        
                    783:                        event_queue_remove(base, ev, EVLIST_ACTIVE);
                    784:                }
                    785: 
                    786:                gettime(base, &now);
                    787:                evutil_timeradd(&now, tv, &ev->ev_timeout);
                    788: 
                    789:                event_debug((
                    790:                         "event_add: timeout in %ld seconds, call %p",
                    791:                         tv->tv_sec, ev->ev_callback));
                    792: 
                    793:                event_queue_insert(base, ev, EVLIST_TIMEOUT);
                    794:        }
                    795: 
                    796:        return (res);
                    797: }
                    798: 
                    799: int
                    800: event_del(struct event *ev)
                    801: {
                    802:        struct event_base *base;
                    803:        const struct eventop *evsel;
                    804:        void *evbase;
                    805: 
                    806:        event_debug(("event_del: %p, callback %p",
                    807:                 ev, ev->ev_callback));
                    808: 
                    809:        /* An event without a base has not been added */
                    810:        if (ev->ev_base == NULL)
                    811:                return (-1);
                    812: 
                    813:        base = ev->ev_base;
                    814:        evsel = base->evsel;
                    815:        evbase = base->evbase;
                    816: 
                    817:        assert(!(ev->ev_flags & ~EVLIST_ALL));
                    818: 
                    819:        /* See if we are just active executing this event in a loop */
                    820:        if (ev->ev_ncalls && ev->ev_pncalls) {
                    821:                /* Abort loop */
                    822:                *ev->ev_pncalls = 0;
                    823:        }
                    824: 
                    825:        if (ev->ev_flags & EVLIST_TIMEOUT)
                    826:                event_queue_remove(base, ev, EVLIST_TIMEOUT);
                    827: 
                    828:        if (ev->ev_flags & EVLIST_ACTIVE)
                    829:                event_queue_remove(base, ev, EVLIST_ACTIVE);
                    830: 
                    831:        if (ev->ev_flags & EVLIST_INSERTED) {
                    832:                event_queue_remove(base, ev, EVLIST_INSERTED);
                    833:                return (evsel->del(evbase, ev));
                    834:        }
                    835: 
                    836:        return (0);
                    837: }
                    838: 
                    839: void
                    840: event_active(struct event *ev, int res, short ncalls)
                    841: {
                    842:        /* We get different kinds of events, add them together */
                    843:        if (ev->ev_flags & EVLIST_ACTIVE) {
                    844:                ev->ev_res |= res;
                    845:                return;
                    846:        }
                    847: 
                    848:        ev->ev_res = res;
                    849:        ev->ev_ncalls = ncalls;
                    850:        ev->ev_pncalls = NULL;
                    851:        event_queue_insert(ev->ev_base, ev, EVLIST_ACTIVE);
                    852: }
                    853: 
                    854: static int
                    855: timeout_next(struct event_base *base, struct timeval **tv_p)
                    856: {
                    857:        struct timeval now;
                    858:        struct event *ev;
                    859:        struct timeval *tv = *tv_p;
                    860: 
                    861:        if ((ev = min_heap_top(&base->timeheap)) == NULL) {
                    862:                /* if no time-based events are active wait for I/O */
                    863:                *tv_p = NULL;
                    864:                return (0);
                    865:        }
                    866: 
                    867:        if (gettime(base, &now) == -1)
                    868:                return (-1);
                    869: 
                    870:        if (evutil_timercmp(&ev->ev_timeout, &now, <=)) {
                    871:                evutil_timerclear(tv);
                    872:                return (0);
                    873:        }
                    874: 
                    875:        evutil_timersub(&ev->ev_timeout, &now, tv);
                    876: 
                    877:        assert(tv->tv_sec >= 0);
                    878:        assert(tv->tv_usec >= 0);
                    879: 
                    880:        event_debug(("timeout_next: in %ld seconds", tv->tv_sec));
                    881:        return (0);
                    882: }
                    883: 
                    884: /*
                    885:  * Determines if the time is running backwards by comparing the current
                    886:  * time against the last time we checked.  Not needed when using clock
                    887:  * monotonic.
                    888:  */
                    889: 
                    890: static void
                    891: timeout_correct(struct event_base *base, struct timeval *tv)
                    892: {
                    893:        struct event **pev;
                    894:        unsigned int size;
                    895:        struct timeval off;
                    896: 
                    897:        if (use_monotonic)
                    898:                return;
                    899: 
                    900:        /* Check if time is running backwards */
                    901:        gettime(base, tv);
                    902:        if (evutil_timercmp(tv, &base->event_tv, >=)) {
                    903:                base->event_tv = *tv;
                    904:                return;
                    905:        }
                    906: 
                    907:        event_debug(("%s: time is running backwards, corrected",
                    908:                    __func__));
                    909:        evutil_timersub(&base->event_tv, tv, &off);
                    910: 
                    911:        /*
                    912:         * We can modify the key element of the node without destroying
                    913:         * the key, beause we apply it to all in the right order.
                    914:         */
                    915:        pev = base->timeheap.p;
                    916:        size = base->timeheap.n;
                    917:        for (; size-- > 0; ++pev) {
                    918:                struct timeval *ev_tv = &(**pev).ev_timeout;
                    919:                evutil_timersub(ev_tv, &off, ev_tv);
                    920:        }
                    921:        /* Now remember what the new time turned out to be. */
                    922:        base->event_tv = *tv;
                    923: }
                    924: 
                    925: void
                    926: timeout_process(struct event_base *base)
                    927: {
                    928:        struct timeval now;
                    929:        struct event *ev;
                    930: 
                    931:        if (min_heap_empty(&base->timeheap))
                    932:                return;
                    933: 
                    934:        gettime(base, &now);
                    935: 
                    936:        while ((ev = min_heap_top(&base->timeheap))) {
                    937:                if (evutil_timercmp(&ev->ev_timeout, &now, >))
                    938:                        break;
                    939: 
                    940:                /* delete this event from the I/O queues */
                    941:                event_del(ev);
                    942: 
                    943:                event_debug(("timeout_process: call %p",
                    944:                         ev->ev_callback));
                    945:                event_active(ev, EV_TIMEOUT, 1);
                    946:        }
                    947: }
                    948: 
                    949: void
                    950: event_queue_remove(struct event_base *base, struct event *ev, int queue)
                    951: {
                    952:        if (!(ev->ev_flags & queue))
                    953:                event_errx(1, "%s: %p(fd %d) not on queue %x", __func__,
                    954:                           ev, ev->ev_fd, queue);
                    955: 
                    956:        if (~ev->ev_flags & EVLIST_INTERNAL)
                    957:                base->event_count--;
                    958: 
                    959:        ev->ev_flags &= ~queue;
                    960:        switch (queue) {
                    961:        case EVLIST_INSERTED:
                    962:                TAILQ_REMOVE(&base->eventqueue, ev, ev_next);
                    963:                break;
                    964:        case EVLIST_ACTIVE:
                    965:                base->event_count_active--;
                    966:                TAILQ_REMOVE(base->activequeues[ev->ev_pri],
                    967:                    ev, ev_active_next);
                    968:                break;
                    969:        case EVLIST_TIMEOUT:
                    970:                min_heap_erase(&base->timeheap, ev);
                    971:                break;
                    972:        default:
                    973:                event_errx(1, "%s: unknown queue %x", __func__, queue);
                    974:        }
                    975: }
                    976: 
                    977: void
                    978: event_queue_insert(struct event_base *base, struct event *ev, int queue)
                    979: {
                    980:        if (ev->ev_flags & queue) {
                    981:                /* Double insertion is possible for active events */
                    982:                if (queue & EVLIST_ACTIVE)
                    983:                        return;
                    984: 
                    985:                event_errx(1, "%s: %p(fd %d) already on queue %x", __func__,
                    986:                           ev, ev->ev_fd, queue);
                    987:        }
                    988: 
                    989:        if (~ev->ev_flags & EVLIST_INTERNAL)
                    990:                base->event_count++;
                    991: 
                    992:        ev->ev_flags |= queue;
                    993:        switch (queue) {
                    994:        case EVLIST_INSERTED:
                    995:                TAILQ_INSERT_TAIL(&base->eventqueue, ev, ev_next);
                    996:                break;
                    997:        case EVLIST_ACTIVE:
                    998:                base->event_count_active++;
                    999:                TAILQ_INSERT_TAIL(base->activequeues[ev->ev_pri],
                   1000:                    ev,ev_active_next);
                   1001:                break;
                   1002:        case EVLIST_TIMEOUT: {
                   1003:                min_heap_push(&base->timeheap, ev);
                   1004:                break;
                   1005:        }
                   1006:        default:
                   1007:                event_errx(1, "%s: unknown queue %x", __func__, queue);
                   1008:        }
                   1009: }
                   1010: 
                   1011: /* Functions for debugging */
                   1012: 
                   1013: const char *
                   1014: event_get_version(void)
                   1015: {
                   1016:        return (VERSION);
                   1017: }
                   1018: 
                   1019: /* 
                   1020:  * No thread-safe interface needed - the information should be the same
                   1021:  * for all threads.
                   1022:  */
                   1023: 
                   1024: const char *
                   1025: event_get_method(void)
                   1026: {
                   1027:        return (current_base->evsel->name);
                   1028: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>