Skip to content
This repository
tree: a7fb9a80ce
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 141 lines (129 sloc) 3.44 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>

#include <errno.h>
#include <string.h>
#include <unistd.h>

#include "evloop.h"

static int m_kq;

static struct kevent m_evs[100];
static uint8_t m_valid[100];

int
evloop_init(void)
{
    if (timeheap_init() != 0)
        return -1;
    m_kq = kqueue();
    return m_kq >= 0 ? 0 : -1;
}

int
fdev_new(struct fdev *ev, int fd, uint16_t flags, evloop_cb_t cb, void *arg)
{
    ev->fd = fd;
    ev->cb = cb;
    ev->arg = arg;
    ev->flags = 0;
    ev->rdidx = -1;
    ev->wridx = -1;
    return fdev_enable(ev, flags);
}

int
fdev_enable(struct fdev *ev, uint16_t flags)
{
    struct kevent kev[2], *kp = NULL;
    int count = 0;
    uint16_t sf = ev->flags;
    ev->flags |= flags;
    if ((sf & EV_READ) == 0 && (flags & EV_READ) != 0) {
        EV_SET(&kev[0], ev->fd, EVFILT_READ, EV_ADD, 0, 0, ev);
        kp = kev;
        count = 1;
    }
    if ((sf & EV_WRITE) == 0 && (flags & EV_WRITE) != 0) {
        EV_SET(&kev[1], ev->fd, EVFILT_WRITE, EV_ADD, 0, 0, ev);
        if (count == 0)
            kp = &kev[1];
        count++;
    }
    return count > 0 ? kevent(m_kq, kp, count, NULL, 0, NULL) : 0;
}

int
fdev_disable(struct fdev *ev, uint16_t flags)
{
    struct kevent kev[2], *kp = NULL;
    int count = 0;
    uint16_t sf = ev->flags;
    ev->flags &= ~flags;
    if ((sf & EV_READ) != 0 && (flags & EV_READ) != 0) {
        EV_SET(&kev[0], ev->fd, EVFILT_READ, EV_DELETE, 0, 0, ev);
        kp = kev;
        count = 1;
    }
    if ((sf & EV_WRITE) != 0 && (flags & EV_WRITE) != 0) {
        EV_SET(&kev[1], ev->fd, EVFILT_WRITE, EV_DELETE, 0, 0, ev);
        if (count == 0)
            kp = &kev[1];
        count++;
    }
    return count > 0 ? kevent(m_kq, kp, count, NULL, 0, NULL) : 0;
}

int
fdev_del(struct fdev *ev)
{
    if (ev->rdidx >= 0)
        m_valid[ev->rdidx] = 0;
    if (ev->wridx >= 0)
        m_valid[ev->wridx] = 0;
    return fdev_disable(ev, EV_READ|EV_WRITE);
}

int
evloop(void)
{
    int nev, i;
    struct timespec delay;
    while (1) {
        evtimers_run();
        delay = evtimer_delay();

        if ((nev = kevent(m_kq, NULL, 0, m_evs, 100, &delay)) < 0) {
            if (errno == EINTR)
                continue;
            else
                return -1;
        }
        memset(m_valid, 1, nev);
        for (i = 0; i < nev; i++) {
            if (m_evs[i].flags & EV_ERROR) {
                errno = m_evs[i].data;
                return -1;
            }
            struct fdev *ev = (struct fdev *)m_evs[i].udata;
            switch (m_evs[i].filter) {
            case EVFILT_READ:
                ev->rdidx = i;
                break;
            case EVFILT_WRITE:
                ev->wridx = i;
                break;
            }
        }
        for (i = 0; i < nev; i++) {
            if (!m_valid[i])
                continue;
            struct fdev *ev = (struct fdev *)m_evs[i].udata;
            switch (m_evs[i].filter) {
            case EVFILT_READ:
                if (ev->flags & EV_READ)
                    ev->cb(ev->fd, EV_READ, ev->arg);
                if (m_valid[i])
                    ev->rdidx = -1;
                break;
            case EVFILT_WRITE:
                if (ev->flags & EV_WRITE)
                    ev->cb(ev->fd, EV_WRITE, ev->arg);
                if (m_valid[i])
                    ev->wridx = -1;
                break;
            }
        }
    }
}
Something went wrong with that request. Please try again.