summaryrefslogtreecommitdiff
path: root/src/fdevent_freebsd_kqueue.c
diff options
context:
space:
mode:
authorOlaf van der Spek <olafvdspek@gmail.com>2010-08-23 21:41:54 +0000
committerOlaf van der Spek <olafvdspek@gmail.com>2010-08-23 21:41:54 +0000
commita85840baef48307ba44719ae44bbb0ca801c30a2 (patch)
treefdfdb1aefa733b99259eae4618de831940241d32 /src/fdevent_freebsd_kqueue.c
parentb0a9856092499507b786855095a89975c1f9ce35 (diff)
downloadlighttpd-a85840baef48307ba44719ae44bbb0ca801c30a2.tar.gz
Upstream 1.4.28
Diffstat (limited to 'src/fdevent_freebsd_kqueue.c')
-rw-r--r--src/fdevent_freebsd_kqueue.c53
1 files changed, 41 insertions, 12 deletions
diff --git a/src/fdevent_freebsd_kqueue.c b/src/fdevent_freebsd_kqueue.c
index b4e862c..0f53a2a 100644
--- a/src/fdevent_freebsd_kqueue.c
+++ b/src/fdevent_freebsd_kqueue.c
@@ -22,20 +22,31 @@ static void fdevent_freebsd_kqueue_free(fdevents *ev) {
}
static int fdevent_freebsd_kqueue_event_del(fdevents *ev, int fde_ndx, int fd) {
- int ret;
+ int ret, n = 0;
struct kevent kev[2];
struct timespec ts;
+ int oevents;
if (fde_ndx < 0) return -1;
- EV_SET(&kev[0], fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
- EV_SET(&kev[1], fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
+ oevents = ev->fdarray[fd]->events;
+
+ if (oevents & FDEVENT_IN) {
+ EV_SET(&kev[n], fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
+ n++;
+ }
+ if (oevents & FDEVENT_OUT) {
+ EV_SET(&kev[n], fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
+ n++;
+ }
+
+ if (0 == n) return -1;
ts.tv_sec = 0;
ts.tv_nsec = 0;
ret = kevent(ev->kq_fd,
- &kev, 2,
+ &kev, n,
NULL, 0,
&ts);
@@ -49,28 +60,46 @@ static int fdevent_freebsd_kqueue_event_del(fdevents *ev, int fde_ndx, int fd) {
return -1;
}
-static int fdevent_freebsd_kqueue_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
- int filter, ret;
- struct kevent kev;
+static int fdevent_freebsd_kqueue_event_set(fdevents *ev, int fde_ndx, int fd, int events) {
+ int ret, n = 0;
+ struct kevent kev[2];
struct timespec ts;
+ int oevents = ev->fdarray[fd]->events;
+ int addevents = events & ~oevents;
+ int delevents = ~events & oevents;
UNUSED(fde_ndx);
- filter = (events & FDEVENT_IN) ? EVFILT_READ : EVFILT_WRITE;
+ if (events == oevents) return fd;
+
+ if (addevents & FDEVENT_IN) {
+ EV_SET(&kev[n], fd, EVFILT_READ, EV_ADD|EV_CLEAR, 0, 0, NULL);
+ n++;
+ } else if (delevents & FDEVENT_IN) {
+ EV_SET(&kev[n], fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
+ n++;
+ }
+ if (addevents & FDEVENT_OUT) {
+ EV_SET(&kev[n], fd, EVFILT_WRITE, EV_ADD|EV_CLEAR, 0, 0, NULL);
+ n++;
+ } else if (delevents & FDEVENT_OUT) {
+ EV_SET(&kev[n], fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
+ n++;
+ }
- EV_SET(&kev, fd, filter, EV_ADD|EV_CLEAR, 0, 0, NULL);
+ if (0 == n) return fd;
ts.tv_sec = 0;
ts.tv_nsec = 0;
ret = kevent(ev->kq_fd,
- &kev, 1,
+ kev, n,
NULL, 0,
&ts);
if (ret == -1) {
log_error_write(ev->srv, __FILE__, __LINE__, "SS",
- "kqueue event add failed: ", strerror(errno));
+ "kqueue event set failed: ", strerror(errno));
return -1;
}
@@ -161,7 +190,7 @@ int fdevent_freebsd_kqueue_init(fdevents *ev) {
SET(reset);
SET(event_del);
- SET(event_add);
+ SET(event_set);
SET(event_next_fdndx);
SET(event_get_fd);