- next is 1.4.56
[lighttpd.git] / src / fdevent_poll.c
blob11636f2c8d66ff898eaa1325060088aaf1ad4fd1
1 #include "first.h"
3 #include "fdevent_impl.h"
4 #include "fdevent.h"
5 #include "buffer.h"
7 #include <unistd.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <errno.h>
12 #ifdef FDEVENT_USE_POLL
14 # ifdef HAVE_POLL_H
15 # include <poll.h>
16 # else
17 # include <sys/poll.h>
18 # endif
20 __attribute_cold__
21 static void fdevent_poll_free(fdevents *ev) {
22 free(ev->pollfds);
23 if (ev->unused.ptr) free(ev->unused.ptr);
26 static int fdevent_poll_event_del(fdevents *ev, fdnode *fdn) {
27 int fd = fdn->fd;
28 int k = fdn->fde_ndx;
29 if ((size_t)k >= ev->used || ev->pollfds[k].fd != fd) return (errno = EINVAL, -1);
31 ev->pollfds[k].fd = -1;
32 /* ev->pollfds[k].events = 0; */
33 /* ev->pollfds[k].revents = 0; */
35 if (ev->unused.size == ev->unused.used) {
36 ev->unused.size += 16;
37 ev->unused.ptr = realloc(ev->unused.ptr, sizeof(*(ev->unused.ptr)) * ev->unused.size);
38 force_assert(NULL != ev->unused.ptr);
41 ev->unused.ptr[ev->unused.used++] = k;
43 return 0;
46 static int fdevent_poll_event_set(fdevents *ev, fdnode *fdn, int events) {
47 int fd = fdn->fd;
48 int k = fdn->fde_ndx;
50 #ifndef POLLRDHUP
51 events &= ~FDEVENT_RDHUP;
52 #endif
54 if (k >= 0) {
55 if ((size_t)k >= ev->used || ev->pollfds[k].fd != fd) return (errno = EINVAL, -1);
56 ev->pollfds[k].events = events;
57 return 0;
60 if (ev->unused.used > 0) {
61 k = ev->unused.ptr[--ev->unused.used];
63 } else {
64 if (ev->size == ev->used) {
65 ev->size += 16;
66 ev->pollfds = realloc(ev->pollfds, sizeof(*ev->pollfds) * ev->size);
67 force_assert(NULL != ev->pollfds);
70 k = ev->used++;
73 fdn->fde_ndx = k;
74 ev->pollfds[k].fd = fd;
75 ev->pollfds[k].events = events;
77 return 0;
80 static int fdevent_poll_next_ndx(const fdevents *ev, int ndx) {
81 for (size_t i = (size_t)(ndx+1); i < ev->used; ++i) {
82 if (ev->pollfds[i].revents) return i;
84 return -1;
87 static int fdevent_poll_poll(fdevents *ev, int timeout_ms) {
88 const int n = poll(ev->pollfds, ev->used, timeout_ms);
89 server * const srv = ev->srv;
90 for (int ndx=-1,i=0; i<n && -1!=(ndx=fdevent_poll_next_ndx(ev,ndx)); ++i){
91 fdnode *fdn = ev->fdarray[ev->pollfds[ndx].fd];
92 int revents = ev->pollfds[ndx].revents;
93 if (0 == ((uintptr_t)fdn & 0x3)) {
94 (*fdn->handler)(srv, fdn->ctx, revents);
97 return n;
100 __attribute_cold__
101 int fdevent_poll_init(fdevents *ev) {
102 force_assert(POLLIN == FDEVENT_IN);
103 force_assert(POLLPRI == FDEVENT_PRI);
104 force_assert(POLLOUT == FDEVENT_OUT);
105 force_assert(POLLERR == FDEVENT_ERR);
106 force_assert(POLLHUP == FDEVENT_HUP);
107 force_assert(POLLNVAL == FDEVENT_NVAL);
108 #ifdef POLLRDHUP
109 force_assert(POLLRDHUP == FDEVENT_RDHUP);
110 #endif
112 ev->type = FDEVENT_HANDLER_POLL;
113 ev->event_set = fdevent_poll_event_set;
114 ev->event_del = fdevent_poll_event_del;
115 ev->poll = fdevent_poll_poll;
116 ev->free = fdevent_poll_free;
117 return 0;
120 #endif