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

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

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