Annotation of embedaddon/lighttpd/src/fdevent_freebsd_kqueue.c, revision 1.1.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>