Annotation of embedaddon/lighttpd/src/fdevent_freebsd_kqueue.c, revision 1.1

1.1     ! misho       1: #include "fdevent.h"
        !             2: #include "buffer.h"
        !             3: #include "log.h"
        !             4: 
        !             5: #include <sys/types.h>
        !             6: 
        !             7: #include <unistd.h>
        !             8: #include <stdlib.h>
        !             9: #include <stdio.h>
        !            10: #include <string.h>
        !            11: #include <errno.h>
        !            12: #include <signal.h>
        !            13: #include <fcntl.h>
        !            14: 
        !            15: #ifdef USE_FREEBSD_KQUEUE
        !            16: # include <sys/event.h>
        !            17: # include <sys/time.h>
        !            18: 
        !            19: static void fdevent_freebsd_kqueue_free(fdevents *ev) {
        !            20:        close(ev->kq_fd);
        !            21:        free(ev->kq_results);
        !            22: }
        !            23: 
        !            24: static int fdevent_freebsd_kqueue_event_del(fdevents *ev, int fde_ndx, int fd) {
        !            25:        int ret, n = 0;
        !            26:        struct kevent kev[2];
        !            27:        struct timespec ts;
        !            28:        int oevents;
        !            29: 
        !            30:        if (fde_ndx < 0) return -1;
        !            31: 
        !            32:        oevents = ev->fdarray[fd]->events;
        !            33: 
        !            34:        if (oevents & FDEVENT_IN)  {
        !            35:                EV_SET(&kev[n], fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
        !            36:                n++;
        !            37:        }
        !            38:        if (oevents & FDEVENT_OUT)  {
        !            39:                EV_SET(&kev[n], fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
        !            40:                n++;
        !            41:        }
        !            42: 
        !            43:        if (0 == n) return -1;
        !            44: 
        !            45:        ts.tv_sec  = 0;
        !            46:        ts.tv_nsec = 0;
        !            47: 
        !            48:        ret = kevent(ev->kq_fd,
        !            49:                &kev, n,
        !            50:                NULL, 0,
        !            51:                &ts);
        !            52: 
        !            53:        if (ret == -1) {
        !            54:                log_error_write(ev->srv, __FILE__, __LINE__, "SS",
        !            55:                        "kqueue event delete failed: ", strerror(errno));
        !            56: 
        !            57:                return -1;
        !            58:        }
        !            59: 
        !            60:        return -1;
        !            61: }
        !            62: 
        !            63: static int fdevent_freebsd_kqueue_event_set(fdevents *ev, int fde_ndx, int fd, int events) {
        !            64:        int ret, n = 0;
        !            65:        struct kevent kev[2];
        !            66:        struct timespec ts;
        !            67:        int oevents = ev->fdarray[fd]->events;
        !            68:        int addevents = events & ~oevents;
        !            69:        int delevents = ~events & oevents;
        !            70: 
        !            71:        UNUSED(fde_ndx);
        !            72: 
        !            73:        if (events == oevents) return fd;
        !            74: 
        !            75:        if (addevents & FDEVENT_IN)  {
        !            76:                EV_SET(&kev[n], fd, EVFILT_READ, EV_ADD|EV_CLEAR, 0, 0, NULL);
        !            77:                n++;
        !            78:        } else if (delevents & FDEVENT_IN) {
        !            79:                EV_SET(&kev[n], fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
        !            80:                n++;
        !            81:        }
        !            82:        if (addevents & FDEVENT_OUT)  {
        !            83:                EV_SET(&kev[n], fd, EVFILT_WRITE, EV_ADD|EV_CLEAR, 0, 0, NULL);
        !            84:                n++;
        !            85:        } else if (delevents & FDEVENT_OUT) {
        !            86:                EV_SET(&kev[n], fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
        !            87:                n++;
        !            88:        }
        !            89: 
        !            90:        if (0 == n) return fd;
        !            91: 
        !            92:        ts.tv_sec  = 0;
        !            93:        ts.tv_nsec = 0;
        !            94: 
        !            95:        ret = kevent(ev->kq_fd,
        !            96:                kev, n,
        !            97:                NULL, 0,
        !            98:                &ts);
        !            99: 
        !           100:        if (ret == -1) {
        !           101:                log_error_write(ev->srv, __FILE__, __LINE__, "SS",
        !           102:                        "kqueue event set failed: ", strerror(errno));
        !           103: 
        !           104:                return -1;
        !           105:        }
        !           106: 
        !           107:        return fd;
        !           108: }
        !           109: 
        !           110: static int fdevent_freebsd_kqueue_poll(fdevents *ev, int timeout_ms) {
        !           111:        int ret;
        !           112:        struct timespec ts;
        !           113: 
        !           114:        ts.tv_sec  = timeout_ms / 1000;
        !           115:        ts.tv_nsec = (timeout_ms % 1000) * 1000000;
        !           116: 
        !           117:        ret = kevent(ev->kq_fd,
        !           118:                NULL, 0,
        !           119:                ev->kq_results, ev->maxfds,
        !           120:                &ts);
        !           121: 
        !           122:        if (ret == -1) {
        !           123:                switch(errno) {
        !           124:                case EINTR:
        !           125:                        /* we got interrupted, perhaps just a SIGCHLD of a CGI script */
        !           126:                        return 0;
        !           127:                default:
        !           128:                        log_error_write(ev->srv, __FILE__, __LINE__, "SS",
        !           129:                                "kqueue failed polling: ", strerror(errno));
        !           130:                        break;
        !           131:                }
        !           132:        }
        !           133: 
        !           134:        return ret;
        !           135: }
        !           136: 
        !           137: static int fdevent_freebsd_kqueue_event_get_revent(fdevents *ev, size_t ndx) {
        !           138:        int events = 0, e;
        !           139: 
        !           140:        e = ev->kq_results[ndx].filter;
        !           141: 
        !           142:        if (e == EVFILT_READ) {
        !           143:                events |= FDEVENT_IN;
        !           144:        } else if (e == EVFILT_WRITE) {
        !           145:                events |= FDEVENT_OUT;
        !           146:        }
        !           147: 
        !           148:        e = ev->kq_results[ndx].flags;
        !           149: 
        !           150:        if (e & EV_EOF) {
        !           151:                events |= FDEVENT_HUP;
        !           152:        }
        !           153: 
        !           154:        if (e & EV_ERROR) {
        !           155:                events |= FDEVENT_ERR;
        !           156:        }
        !           157: 
        !           158:        return events;
        !           159: }
        !           160: 
        !           161: static int fdevent_freebsd_kqueue_event_get_fd(fdevents *ev, size_t ndx) {
        !           162:        return ev->kq_results[ndx].ident;
        !           163: }
        !           164: 
        !           165: static int fdevent_freebsd_kqueue_event_next_fdndx(fdevents *ev, int ndx) {
        !           166:        UNUSED(ev);
        !           167: 
        !           168:        return (ndx < 0) ? 0 : ndx + 1;
        !           169: }
        !           170: 
        !           171: static int fdevent_freebsd_kqueue_reset(fdevents *ev) {
        !           172:        if (-1 == (ev->kq_fd = kqueue())) {
        !           173:                log_error_write(ev->srv, __FILE__, __LINE__, "SSS",
        !           174:                        "kqueue failed (", strerror(errno), "), try to set server.event-handler = \"poll\" or \"select\"");
        !           175: 
        !           176:                return -1;
        !           177:        }
        !           178: 
        !           179:        return 0;
        !           180: }
        !           181: 
        !           182: 
        !           183: int fdevent_freebsd_kqueue_init(fdevents *ev) {
        !           184:        ev->type = FDEVENT_HANDLER_FREEBSD_KQUEUE;
        !           185: #define SET(x) \
        !           186:        ev->x = fdevent_freebsd_kqueue_##x;
        !           187: 
        !           188:        SET(free);
        !           189:        SET(poll);
        !           190:        SET(reset);
        !           191: 
        !           192:        SET(event_del);
        !           193:        SET(event_set);
        !           194: 
        !           195:        SET(event_next_fdndx);
        !           196:        SET(event_get_fd);
        !           197:        SET(event_get_revent);
        !           198: 
        !           199:        ev->kq_fd = -1;
        !           200: 
        !           201:        ev->kq_results = calloc(ev->maxfds, sizeof(*ev->kq_results));
        !           202: 
        !           203:        /* check that kqueue works */
        !           204: 
        !           205:        if (-1 == (ev->kq_fd = kqueue())) {
        !           206:                log_error_write(ev->srv, __FILE__, __LINE__, "SSS",
        !           207:                        "kqueue failed (", strerror(errno), "), try to set server.event-handler = \"poll\" or \"select\"");
        !           208: 
        !           209:                return -1;
        !           210:        }
        !           211: 
        !           212:        close(ev->kq_fd);
        !           213:        ev->kq_fd = -1;
        !           214: 
        !           215:        return 0;
        !           216: }
        !           217: #else
        !           218: int fdevent_freebsd_kqueue_init(fdevents *ev) {
        !           219:        UNUSED(ev);
        !           220: 
        !           221:        log_error_write(ev->srv, __FILE__, __LINE__, "S",
        !           222:                "kqueue not available, try to set server.event-handler = \"poll\" or \"select\"");
        !           223: 
        !           224:        return -1;
        !           225: }
        !           226: #endif

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