59 #include <sys/queue.h>
69 #ifdef CHECK_INVARIANTS
74 #include "event-internal.h"
84 #define DEFAULT_NFDS 16
92 #define EVENTS_PER_GETN 8
100 struct event* fdi_revt;
101 struct event* fdi_wevt;
104 #define FDI_HAS_READ(fdi) ((fdi)->fdi_revt != NULL)
105 #define FDI_HAS_WRITE(fdi) ((fdi)->fdi_wevt != NULL)
106 #define FDI_HAS_EVENTS(fdi) (FDI_HAS_READ(fdi) || FDI_HAS_WRITE(fdi))
107 #define FDI_TO_SYSEVENTS(fdi) (FDI_HAS_READ(fdi) ? POLLIN : 0) | \
108 (FDI_HAS_WRITE(fdi) ? POLLOUT : 0)
115 int ed_pending[EVENTS_PER_GETN];
118 static void* evport_init (
struct event_base *);
119 static int evport_add (
void *,
struct event *);
120 static int evport_del (
void *,
struct event *);
122 static void evport_dealloc (
struct event_base *,
void *);
124 const struct eventop evportops = {
146 if (getenv(
"EVENT_NOEVPORT"))
149 if (!(evpd = calloc(1,
sizeof(
struct evport_data))))
152 if ((evpd->ed_port = port_create()) == -1) {
160 evpd->ed_fds = calloc(DEFAULT_NFDS,
sizeof(
struct fd_info));
161 if (evpd->ed_fds == NULL) {
162 close(evpd->ed_port);
166 evpd->ed_nevents = DEFAULT_NFDS;
167 for (i = 0; i < EVENTS_PER_GETN; i++)
168 evpd->ed_pending[i] = -1;
175 #ifdef CHECK_INVARIANTS
186 assert(evpd->ed_nevents > 0);
187 assert(evpd->ed_port > 0);
188 assert(evpd->ed_fds > 0);
196 for (i = 0; i < evpd->ed_nevents; ++
i) {
200 fdi = &evpd->ed_fds[
i];
201 if ((ev = fdi->fdi_revt) != NULL) {
202 assert(ev->ev_fd == i);
204 if ((ev = fdi->fdi_wevt) != NULL) {
205 assert(ev->ev_fd == i);
214 check_event(port_event_t* pevt)
222 assert(pevt->portev_source == PORT_SOURCE_FD);
223 assert(pevt->portev_user == NULL);
227 #define check_evportop(epop)
228 #define check_event(pevt)
238 int oldsize = epdp->ed_nevents;
239 int newsize = factor * oldsize;
242 check_evportop(epdp);
244 tmp = realloc(epdp->ed_fds,
sizeof(
struct fd_info) * newsize);
248 memset((
char*) (epdp->ed_fds + oldsize), 0,
249 (newsize - oldsize)*
sizeof(
struct fd_info));
250 epdp->ed_nevents = newsize;
252 check_evportop(epdp);
265 int sysevents = FDI_TO_SYSEVENTS(fdip);
267 if (sysevents != 0) {
268 if (port_associate(epdp->ed_port, PORT_SOURCE_FD,
269 fd, sysevents, NULL) == -1) {
270 event_warn(
"port_associate");
275 check_evportop(epdp);
290 port_event_t pevtlist[EVENTS_PER_GETN];
308 ts.tv_sec = tv->tv_sec;
309 ts.tv_nsec = tv->tv_usec * 1000;
318 for (i = 0; i < EVENTS_PER_GETN; ++
i) {
320 if (epdp->ed_pending[i] != -1) {
321 fdi = &(epdp->ed_fds[epdp->ed_pending[
i]]);
324 if (fdi != NULL && FDI_HAS_EVENTS(fdi)) {
325 int fd = FDI_HAS_READ(fdi) ? fdi->fdi_revt->ev_fd :
326 fdi->fdi_wevt->ev_fd;
327 reassociate(epdp, fdi, fd);
328 epdp->ed_pending[
i] = -1;
332 if ((res = port_getn(epdp->ed_port, pevtlist, EVENTS_PER_GETN,
333 (
unsigned int *) &nevents, ts_p)) == -1) {
334 if (errno == EINTR || errno == EAGAIN) {
335 evsignal_process(base);
337 }
else if (errno == ETIME) {
341 event_warn(
"port_getn");
344 }
else if (base->sig.evsignal_caught) {
345 evsignal_process(base);
348 event_debug((
"%s: port_getn reports %d events", __func__, nevents));
350 for (i = 0; i < nevents; ++
i) {
353 port_event_t *pevt = &pevtlist[
i];
354 int fd = (int) pevt->portev_object;
356 check_evportop(epdp);
358 epdp->ed_pending[
i] = fd;
365 if (pevt->portev_events & POLLIN)
367 if (pevt->portev_events & POLLOUT)
370 assert(epdp->ed_nevents > fd);
371 fdi = &(epdp->ed_fds[fd]);
379 if ((res & EV_READ) && ((ev = fdi->fdi_revt) != NULL)) {
380 event_active(ev, res, 1);
383 if ((res & EV_WRITE) && ((ev = fdi->fdi_wevt) != NULL)) {
384 event_active(ev, res, 1);
388 check_evportop(epdp);
400 evport_add(
void *arg,
struct event *ev)
406 check_evportop(evpd);
411 if (ev->ev_events & EV_SIGNAL)
412 return (evsignal_add(ev));
419 while (ev->ev_fd >= factor * evpd->ed_nevents)
423 if (-1 == grow(evpd, factor)) {
428 fdi = &evpd->ed_fds[ev->ev_fd];
429 if (ev->ev_events & EV_READ)
431 if (ev->ev_events & EV_WRITE)
434 return reassociate(evpd, fdi, ev->ev_fd);
442 evport_del(
void *arg,
struct event *ev)
449 check_evportop(evpd);
454 if (ev->ev_events & EV_SIGNAL) {
455 return (evsignal_del(ev));
458 if (evpd->ed_nevents < ev->ev_fd) {
462 for (i = 0; i < EVENTS_PER_GETN; ++
i) {
463 if (evpd->ed_pending[i] == ev->ev_fd) {
469 fdi = &evpd->ed_fds[ev->ev_fd];
470 if (ev->ev_events & EV_READ)
471 fdi->fdi_revt = NULL;
472 if (ev->ev_events & EV_WRITE)
473 fdi->fdi_wevt = NULL;
476 if (!FDI_HAS_EVENTS(fdi) &&
477 port_dissociate(evpd->ed_port, PORT_SOURCE_FD,
483 if (errno != EBADFD) {
484 event_warn(
"port_dissociate");
488 if (FDI_HAS_EVENTS(fdi)) {
489 return (reassociate(evpd, fdi, ev->ev_fd));
493 if (fdi->fdi_revt == NULL && fdi->fdi_wevt == NULL) {
494 evpd->ed_pending[
i] = -1;
502 evport_dealloc(
struct event_base *base,
void *arg)
506 evsignal_dealloc(base);
508 close(evpd->ed_port);