31 #include <sys/types.h>
32 #include <sys/resource.h>
33 #ifdef HAVE_SYS_TIME_H
36 #include <sys/_time.h>
38 #include <sys/queue.h>
39 #include <sys/devpoll.h>
50 #include "event-internal.h"
59 struct event *evwrite;
65 struct pollfd *events;
68 struct pollfd *changes;
72 static void *devpoll_init (
struct event_base *);
73 static int devpoll_add (
void *,
struct event *);
74 static int devpoll_del (
void *,
struct event *);
76 static void devpoll_dealloc (
struct event_base *,
void *);
78 const struct eventop devpollops = {
97 if (pwrite(devpollop->dpfd, devpollop->changes,
98 sizeof(
struct pollfd) * devpollop->nchanges, 0) == -1)
101 devpollop->nchanges = 0;
106 devpoll_queue(
struct devpollop *devpollop,
int fd,
int events) {
109 if (devpollop->nchanges >= devpollop->nevents) {
114 if (devpoll_commit(devpollop) != 0)
118 pfd = &devpollop->changes[devpollop->nchanges++];
120 pfd->events = events;
129 int dpfd, nfiles = NEVENT;
131 struct devpollop *devpollop;
134 if (getenv(
"EVENT_NODEVPOLL"))
137 if (!(devpollop = calloc(1,
sizeof(
struct devpollop))))
140 if (getrlimit(RLIMIT_NOFILE, &rl) == 0 &&
141 rl.rlim_cur != RLIM_INFINITY)
142 nfiles = rl.rlim_cur;
145 if ((dpfd = open(
"/dev/poll", O_RDWR)) == -1) {
146 event_warn(
"open: /dev/poll");
151 devpollop->dpfd = dpfd;
154 devpollop->events = calloc(nfiles,
sizeof(
struct pollfd));
155 if (devpollop->events == NULL) {
160 devpollop->nevents = nfiles;
162 devpollop->fds = calloc(nfiles,
sizeof(
struct evdevpoll));
163 if (devpollop->fds == NULL) {
164 free(devpollop->events);
169 devpollop->nfds = nfiles;
171 devpollop->changes = calloc(nfiles,
sizeof(
struct pollfd));
172 if (devpollop->changes == NULL) {
173 free(devpollop->fds);
174 free(devpollop->events);
186 devpoll_recalc(
struct event_base *base,
void *arg,
int max)
188 struct devpollop *devpollop = arg;
190 if (max >= devpollop->nfds) {
194 nfds = devpollop->nfds;
198 fds = realloc(devpollop->fds, nfds *
sizeof(
struct evdevpoll));
200 event_warn(
"realloc");
203 devpollop->fds = fds;
204 memset(fds + devpollop->nfds, 0,
205 (nfds - devpollop->nfds) *
sizeof(
struct evdevpoll));
206 devpollop->nfds = nfds;
215 struct devpollop *devpollop = arg;
216 struct pollfd *events = devpollop->events;
219 int i, res, timeout = -1;
221 if (devpollop->nchanges)
222 devpoll_commit(devpollop);
225 timeout = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000;
227 dvp.dp_fds = devpollop->events;
228 dvp.dp_nfds = devpollop->nevents;
229 dvp.dp_timeout = timeout;
231 res = ioctl(devpollop->dpfd, DP_POLL, &dvp);
234 if (errno != EINTR) {
235 event_warn(
"ioctl: DP_POLL");
239 evsignal_process(base);
241 }
else if (base->sig.evsignal_caught) {
242 evsignal_process(base);
245 event_debug((
"%s: devpoll_wait reports %d", __func__, res));
247 for (i = 0; i < res; i++) {
249 int what = events[
i].revents;
250 struct event *evread = NULL, *evwrite = NULL;
252 assert(events[i].fd < devpollop->nfds);
253 evdp = &devpollop->fds[events[
i].fd];
256 what |= POLLIN | POLLOUT;
257 else if (what & POLLERR)
258 what |= POLLIN | POLLOUT;
261 evread = evdp->evread;
265 if (what & POLLOUT) {
266 evwrite = evdp->evwrite;
273 if (evread != NULL && !(evread->ev_events & EV_PERSIST))
275 if (evwrite != NULL && evwrite != evread &&
276 !(evwrite->ev_events & EV_PERSIST))
280 event_active(evread, EV_READ, 1);
282 event_active(evwrite, EV_WRITE, 1);
290 devpoll_add(
void *arg,
struct event *ev)
292 struct devpollop *devpollop = arg;
296 if (ev->ev_events & EV_SIGNAL)
297 return (evsignal_add(ev));
300 if (fd >= devpollop->nfds) {
302 if (devpoll_recalc(ev->ev_base, devpollop, fd) == -1)
305 evdp = &devpollop->fds[fd];
315 if (ev->ev_events & EV_READ) {
316 if (evdp->evread && evdp->evread != ev) {
323 if (ev->ev_events & EV_WRITE) {
324 if (evdp->evwrite && evdp->evwrite != ev) {
331 if (devpoll_queue(devpollop, fd, events) != 0)
335 if (ev->ev_events & EV_READ)
337 if (ev->ev_events & EV_WRITE)
344 devpoll_del(
void *arg,
struct event *ev)
346 struct devpollop *devpollop = arg;
349 int needwritedelete = 1, needreaddelete = 1;
351 if (ev->ev_events & EV_SIGNAL)
352 return (evsignal_del(ev));
355 if (fd >= devpollop->nfds)
357 evdp = &devpollop->fds[fd];
360 if (ev->ev_events & EV_READ)
362 if (ev->ev_events & EV_WRITE)
372 if (devpoll_queue(devpollop, fd, POLLREMOVE) != 0)
375 if ((events & (POLLIN|POLLOUT)) != (POLLIN|POLLOUT)) {
381 if ((events & POLLIN) && evdp->evwrite != NULL) {
383 devpoll_queue(devpollop, fd, POLLOUT);
385 }
else if ((events & POLLOUT) && evdp->evread != NULL) {
387 devpoll_queue(devpollop, fd, POLLIN);
395 evdp->evwrite = NULL;
401 devpoll_dealloc(
struct event_base *base,
void *arg)
403 struct devpollop *devpollop = arg;
405 evsignal_dealloc(base);
407 free(devpollop->fds);
408 if (devpollop->events)
409 free(devpollop->events);
410 if (devpollop->changes)
411 free(devpollop->changes);
412 if (devpollop->dpfd >= 0)
413 close(devpollop->dpfd);
415 memset(devpollop, 0,
sizeof(
struct devpollop));