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>