--- libev/ev_epoll.c 2008/10/29 07:09:37 1.40 +++ libev/ev_epoll.c 2010/04/21 13:13:18 1.51 @@ -1,7 +1,7 @@ /* * libev epoll fd activity backend * - * Copyright (c) 2007,2008 Marc Alexander Lehmann + * Copyright (c) 2007,2008,2009,2010 Marc Alexander Lehmann * All rights reserved. * * Redistribution and use in source and binary forms, with or without modifica- @@ -49,6 +49,11 @@ * c) the inability to handle fork or file descriptors (think dup) * limits the applicability over poll, so this is not a generic * poll replacement. + * d) epoll doesn't work the same as select with many file descriptors + * (such as files). while not critical, no other advanced interface + * seems to share this (rather non-unixy) limitation. + * e) epoll claims to be embeddable, but in practise you never get + * a ready event for the epoll fd. * * lots of "weird code" and complication handling in this file is due * to these design problems with epoll, as we try very hard to avoid @@ -70,7 +75,7 @@ * on the assumption that the fd is gone anyways * if that is wrong, we have to handle the spurious * event in epoll_poll. - * the fd is later added, we try to ADD it, and, if that + * if the fd is added again, we try to ADD it, and, if that * fails, we assume it still has the same eventmask. */ if (!nev) @@ -79,12 +84,13 @@ oldmask = anfds [fd].emask; anfds [fd].emask = nev; - /* store the generation counter in the upper 32 bits */ - ev.data.u64 = fd | ((uint64_t)(uint32_t)++anfds [fd].egen << 32); + /* store the generation counter in the upper 32 bits, the fd in the lower 32 bits */ + ev.data.u64 = (uint64_t)(uint32_t)fd + | ((uint64_t)(uint32_t)++anfds [fd].egen << 32); ev.events = (nev & EV_READ ? EPOLLIN : 0) | (nev & EV_WRITE ? EPOLLOUT : 0); - if (expect_true (!epoll_ctl (backend_fd, oev ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, fd, &ev))) + if (expect_true (!epoll_ctl (backend_fd, oev && oldmask != nev ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, fd, &ev))) return; if (expect_true (errno == ENOENT)) @@ -118,7 +124,13 @@ epoll_poll (EV_P_ ev_tstamp timeout) { int i; - int eventcnt = epoll_wait (backend_fd, epoll_events, epoll_eventmax, (int)ceil (timeout * 1000.)); + int eventcnt; + + /* epoll wait times cannot be larger than (LONG_MAX - 999UL) / HZ msecs, which is below */ + /* the default libev max wait time, however. */ + EV_RELEASE_CB; + eventcnt = epoll_wait (backend_fd, epoll_events, epoll_eventmax, (int)ceil (timeout * 1000.)); + EV_ACQUIRE_CB; if (expect_false (eventcnt < 0)) { @@ -154,6 +166,8 @@ ev->events = (want & EV_READ ? EPOLLIN : 0) | (want & EV_WRITE ? EPOLLOUT : 0); + /* pre-2.6.9 kernels require a non-null pointer with EPOLL_CTL_DEL, */ + /* which is fortunately easy to do for us. */ if (epoll_ctl (backend_fd, want ? EPOLL_CTL_MOD : EPOLL_CTL_DEL, fd, ev)) { postfork = 1; /* an error occured, recreate kernel state */ @@ -176,7 +190,12 @@ int inline_size epoll_init (EV_P_ int flags) { - backend_fd = epoll_create (256); +#ifdef EPOLL_CLOEXEC + backend_fd = epoll_create1 (EPOLL_CLOEXEC); + + if (backend_fd <= 0) +#endif + backend_fd = epoll_create (256); if (backend_fd < 0) return 0;