Browse Source

[core] some fdevent code streamlining

isolate fde_ndx to fdevent framework internals
personal/stbuehler/ci-build
Glenn Strauss 3 years ago
parent
commit
0a46f7ec23
  1. 216
      src/fdevent.c
  2. 6
      src/fdevent.h
  3. 157
      src/fdevent_freebsd_kqueue.c
  4. 12
      src/fdevent_impl.h
  5. 72
      src/fdevent_libev.c
  6. 90
      src/fdevent_linux_sysepoll.c
  7. 83
      src/fdevent_poll.c
  8. 62
      src/fdevent_select.c
  9. 90
      src/fdevent_solaris_devpoll.c
  10. 113
      src/fdevent_solaris_port.c

216
src/fdevent.c

@ -196,66 +196,51 @@ fdevents *fdevent_init(server *srv) {
ev->maxfds = maxfds;
switch(type) {
#ifdef FDEVENT_USE_POLL
case FDEVENT_HANDLER_POLL:
if (0 != fdevent_poll_init(ev)) {
log_error_write(srv, __FILE__, __LINE__, "S",
"event-handler poll failed");
goto error;
}
return ev;
if (0 == fdevent_poll_init(ev)) return ev;
break;
#endif
#ifdef FDEVENT_USE_SELECT
case FDEVENT_HANDLER_SELECT:
if (0 != fdevent_select_init(ev)) {
log_error_write(srv, __FILE__, __LINE__, "S",
"event-handler select failed");
goto error;
}
return ev;
if (0 == fdevent_select_init(ev)) return ev;
break;
#endif
#ifdef FDEVENT_USE_LINUX_EPOLL
case FDEVENT_HANDLER_LINUX_SYSEPOLL:
if (0 != fdevent_linux_sysepoll_init(ev)) {
log_error_write(srv, __FILE__, __LINE__, "S",
"event-handler linux-sysepoll failed, try to set server.event-handler = \"poll\" or \"select\"");
goto error;
}
return ev;
if (0 == fdevent_linux_sysepoll_init(ev)) return ev;
break;
#endif
#ifdef FDEVENT_USE_SOLARIS_DEVPOLL
case FDEVENT_HANDLER_SOLARIS_DEVPOLL:
if (0 != fdevent_solaris_devpoll_init(ev)) {
log_error_write(srv, __FILE__, __LINE__, "S",
"event-handler solaris-devpoll failed, try to set server.event-handler = \"poll\" or \"select\"");
goto error;
}
return ev;
if (0 == fdevent_solaris_devpoll_init(ev)) return ev;
break;
#endif
#ifdef FDEVENT_USE_SOLARIS_PORT
case FDEVENT_HANDLER_SOLARIS_PORT:
if (0 != fdevent_solaris_port_init(ev)) {
log_error_write(srv, __FILE__, __LINE__, "S",
"event-handler solaris-eventports failed, try to set server.event-handler = \"poll\" or \"select\"");
goto error;
}
return ev;
if (0 == fdevent_solaris_port_init(ev)) return ev;
break;
#endif
#ifdef FDEVENT_USE_FREEBSD_KQUEUE
case FDEVENT_HANDLER_FREEBSD_KQUEUE:
if (0 != fdevent_freebsd_kqueue_init(ev)) {
log_error_write(srv, __FILE__, __LINE__, "S",
"event-handler freebsd-kqueue failed, try to set server.event-handler = \"poll\" or \"select\"");
goto error;
}
return ev;
if (0 == fdevent_freebsd_kqueue_init(ev)) return ev;
break;
#endif
#ifdef FDEVENT_USE_LIBEV
case FDEVENT_HANDLER_LIBEV:
if (0 != fdevent_libev_init(ev)) {
log_error_write(srv, __FILE__, __LINE__, "S",
"event-handler libev failed, try to set server.event-handler = \"poll\" or \"select\"");
goto error;
}
return ev;
if (0 == fdevent_libev_init(ev)) return ev;
break;
#endif
case FDEVENT_HANDLER_UNSET:
default:
break;
}
error:
free(ev->fdarray);
free(ev);
log_error_write(srv, __FILE__, __LINE__, "S",
"event-handler is unknown, try to set server.event-handler = \"poll\" or \"select\"");
log_error_write(srv, __FILE__, __LINE__, "sBS",
"event-handler failed:", srv->srvconf.event_handler, "; try to set server.event-handler = \"poll\" or \"select\"");
return NULL;
}
@ -277,59 +262,44 @@ void fdevent_free(fdevents *ev) {
}
int fdevent_reset(fdevents *ev) {
if (ev->reset) return ev->reset(ev);
return 0;
int rc = (NULL != ev->reset) ? ev->reset(ev) : 0;
if (-1 == rc) {
log_error_write(ev->srv, __FILE__, __LINE__, "sBS",
"event-handler failed:", ev->srv->srvconf.event_handler, "; try to set server.event-handler = \"poll\" or \"select\"");
}
return rc;
}
static fdnode *fdnode_init(void) {
fdnode *fdn;
fdn = calloc(1, sizeof(*fdn));
force_assert(NULL != fdn);
fdn->fd = -1;
return fdn;
return calloc(1, sizeof(fdnode));
}
static void fdnode_free(fdnode *fdn) {
free(fdn);
}
int fdevent_register(fdevents *ev, int fd, fdevent_handler handler, void *ctx) {
fdnode *fdn;
fdn = fdnode_init();
void fdevent_register(fdevents *ev, int fd, fdevent_handler handler, void *ctx) {
fdnode *fdn = ev->fdarray[fd] = fdnode_init();
force_assert(NULL != fdn);
fdn->handler = handler;
fdn->fd = fd;
fdn->ctx = ctx;
fdn->events = 0;
fdn->fde_ndx = -1;
#ifdef FDEVENT_USE_LIBEV
fdn->handler_ctx = NULL;
#endif
ev->fdarray[fd] = fdn;
return 0;
}
int fdevent_unregister(fdevents *ev, int fd) {
fdnode *fdn;
if (!ev) return 0;
fdn = ev->fdarray[fd];
if ((uintptr_t)fdn & 0x3) return 0; /*(should not happen)*/
fdnode_free(fdn);
void fdevent_unregister(fdevents *ev, int fd) {
fdnode *fdn = ev->fdarray[fd];
if ((uintptr_t)fdn & 0x3) return; /*(should not happen)*/
ev->fdarray[fd] = NULL;
return 0;
fdnode_free(fdn);
}
void fdevent_sched_close(fdevents *ev, int fd, int issock) {
fdnode *fdn;
if (!ev) return;
fdn = ev->fdarray[fd];
fdnode *fdn = ev->fdarray[fd];
if ((uintptr_t)fdn & 0x3) return;
ev->fdarray[fd] = (fdnode *)((uintptr_t)fdn | (issock ? 0x1 : 0x2));
fdn->ctx = ev->pendclose;
@ -376,72 +346,66 @@ int fdevent_event_get_interest(const fdevents *ev, int fd) {
return fd >= 0 ? ev->fdarray[fd]->events : 0;
}
void fdevent_event_del(fdevents *ev, int *fde_ndx, int fd) {
if (-1 == fd) return;
if ((uintptr_t)ev->fdarray[fd] & 0x3) return;
if (ev->event_del) *fde_ndx = ev->event_del(ev, *fde_ndx, fd);
ev->fdarray[fd]->events = 0;
static void fdevent_fdnode_event_del(fdevents *ev, fdnode *fdn) {
if (-1 == fdn->fde_ndx) return;
if (0 == ev->event_del(ev, fdn)) {
fdn->fde_ndx = -1;
fdn->events = 0;
}
else {
log_error_write(ev->srv, __FILE__, __LINE__, "SS",
"fdevent event_del failed: ", strerror(errno));
}
}
void fdevent_event_set(fdevents *ev, int *fde_ndx, int fd, int events) {
if (-1 == fd) return;
/*(Note: skips registering with kernel if initial events is 0,
* so caller should pass non-zero events for initial registration.
* If never registered due to never being called with non-zero events,
* then FDEVENT_HUP or FDEVENT_ERR will never be returned.) */
if (ev->fdarray[fd]->events == events) return;/*(no change; nothing to do)*/
static void fdevent_fdnode_event_set(fdevents *ev, fdnode *fdn, int events) {
/*(Note: skips registering with kernel if initial events is 0,
* so caller should pass non-zero events for initial registration.
* If never registered due to never being called with non-zero events,
* then FDEVENT_HUP or FDEVENT_ERR will never be returned.) */
if (fdn->events == events) return;/*(no change; nothing to do)*/
if (ev->event_set) *fde_ndx = ev->event_set(ev, *fde_ndx, fd, events);
ev->fdarray[fd]->events = events;
if (0 == ev->event_set(ev, fdn, events))
fdn->events = events;
else
log_error_write(ev->srv, __FILE__, __LINE__, "SS",
"fdevent event_set failed: ", strerror(errno));
}
void fdevent_event_add(fdevents *ev, int *fde_ndx, int fd, int event) {
int events;
if (-1 == fd) return;
void fdevent_event_del(fdevents *ev, int *fde_ndx, int fd) {
UNUSED(fde_ndx);
if (-1 != fd) {
fdnode *fdn = ev->fdarray[fd];
if ((uintptr_t)fdn & 0x3) return;
fdevent_fdnode_event_del(ev, fdn);
}
}
events = ev->fdarray[fd]->events;
if ((events & event) == event) return; /*(no change; nothing to do)*/
void fdevent_event_set(fdevents *ev, int *fde_ndx, int fd, int events) {
UNUSED(fde_ndx);
if (-1 != fd) fdevent_fdnode_event_set(ev, ev->fdarray[fd], events);
}
events |= event;
if (ev->event_set) *fde_ndx = ev->event_set(ev, *fde_ndx, fd, events);
ev->fdarray[fd]->events = events;
void fdevent_event_add(fdevents *ev, int *fde_ndx, int fd, int event) {
UNUSED(fde_ndx);
if (-1 != fd) {
fdnode *fdn = ev->fdarray[fd];
fdevent_fdnode_event_set(ev, fdn, (fdn->events | event));
}
}
void fdevent_event_clr(fdevents *ev, int *fde_ndx, int fd, int event) {
int events;
if (-1 == fd) return;
events = ev->fdarray[fd]->events;
if (!(events & event)) return; /*(no change; nothing to do)*/
events &= ~event;
if (ev->event_set) *fde_ndx = ev->event_set(ev, *fde_ndx, fd, events);
ev->fdarray[fd]->events = events;
UNUSED(fde_ndx);
if (-1 != fd) {
fdnode *fdn = ev->fdarray[fd];
fdevent_fdnode_event_set(ev, fdn, (fdn->events & ~event));
}
}
int fdevent_poll(fdevents *ev, int timeout_ms) {
if (ev->poll == NULL) SEGFAULT();
return ev->poll(ev, timeout_ms);
}
fdevent_handler fdevent_get_handler(fdevents *ev, int fd) {
if (ev->fdarray[fd] == NULL) SEGFAULT();
if ((uintptr_t)ev->fdarray[fd] & 0x3) return NULL;
if (ev->fdarray[fd]->fd != fd) SEGFAULT();
return ev->fdarray[fd]->handler;
}
void * fdevent_get_context(fdevents *ev, int fd) {
if (ev->fdarray[fd] == NULL) SEGFAULT();
if ((uintptr_t)ev->fdarray[fd] & 0x3) return NULL;
if (ev->fdarray[fd]->fd != fd) SEGFAULT();
return ev->fdarray[fd]->ctx;
}
void fdevent_setfd_cloexec(int fd) {
#ifdef FD_CLOEXEC
if (fd < 0) return;

6
src/fdevent.h

@ -55,13 +55,11 @@ void fdevent_event_set(fdevents *ev, int *fde_ndx, int fd, int events); /* event
void fdevent_event_add(fdevents *ev, int *fde_ndx, int fd, int event); /* events can be FDEVENT_IN or FDEVENT_OUT */
void fdevent_event_clr(fdevents *ev, int *fde_ndx, int fd, int event); /* events can be FDEVENT_IN or FDEVENT_OUT */
void fdevent_event_del(fdevents *ev, int *fde_ndx, int fd);
fdevent_handler fdevent_get_handler(fdevents *ev, int fd);
void * fdevent_get_context(fdevents *ev, int fd);
int fdevent_poll(fdevents *ev, int timeout_ms);
int fdevent_register(fdevents *ev, int fd, fdevent_handler handler, void *ctx);
int fdevent_unregister(fdevents *ev, int fd);
void fdevent_register(fdevents *ev, int fd, fdevent_handler handler, void *ctx);
void fdevent_unregister(fdevents *ev, int fd);
void fdevent_sched_close(fdevents *ev, int fd, int issock);
void fdevent_sched_run(struct server *srv, fdevents *ev);

157
src/fdevent_freebsd_kqueue.c

@ -3,34 +3,29 @@
#include "fdevent_impl.h"
#include "fdevent.h"
#include "buffer.h"
#include "log.h"
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#ifdef FDEVENT_USE_FREEBSD_KQUEUE
# include <sys/event.h>
# include <sys/time.h>
__attribute_cold__
static void fdevent_freebsd_kqueue_free(fdevents *ev) {
close(ev->kq_fd);
free(ev->kq_results);
}
static int fdevent_freebsd_kqueue_event_del(fdevents *ev, int fde_ndx, int fd) {
int ret, n = 0;
static int fdevent_freebsd_kqueue_event_del(fdevents *ev, fdnode *fdn) {
struct kevent kev[2];
struct timespec ts;
int oevents;
if (fde_ndx < 0) return -1;
oevents = ev->fdarray[fd]->events;
struct timespec ts = {0, 0};
int fd = fdn->fd;
int n = 0;
int oevents = fdn->events;
if (oevents & FDEVENT_IN) {
EV_SET(&kev[n], fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
@ -41,38 +36,18 @@ static int fdevent_freebsd_kqueue_event_del(fdevents *ev, int fde_ndx, int fd) {
n++;
}
if (0 == n) return -1;
ts.tv_sec = 0;
ts.tv_nsec = 0;
ret = kevent(ev->kq_fd,
kev, n,
NULL, 0,
&ts);
if (ret == -1) {
log_error_write(ev->srv, __FILE__, __LINE__, "SS",
"kqueue event delete failed: ", strerror(errno));
return -1;
}
return -1;
return (0 != n) ? kevent(ev->kq_fd, kev, n, NULL, 0, &ts) : 0;
}
static int fdevent_freebsd_kqueue_event_set(fdevents *ev, int fde_ndx, int fd, int events) {
int ret, n = 0;
static int fdevent_freebsd_kqueue_event_set(fdevents *ev, fdnode *fdn, int events) {
struct kevent kev[2];
struct timespec ts;
int oevents = ev->fdarray[fd]->events;
struct timespec ts = {0, 0};
int fd = fdn->fde_ndx = fdn->fd;
int n = 0;
int oevents = fdn->events;
int addevents = events & ~oevents;
int delevents = ~events & oevents;
UNUSED(fde_ndx);
if (events == oevents) return fd;
if (addevents & FDEVENT_IN) {
EV_SET(&kev[n], fd, EVFILT_READ, EV_ADD, 0, 0, NULL);
n++;
@ -88,50 +63,7 @@ static int fdevent_freebsd_kqueue_event_set(fdevents *ev, int fde_ndx, int fd, i
n++;
}
if (0 == n) return fd;
ts.tv_sec = 0;
ts.tv_nsec = 0;
ret = kevent(ev->kq_fd,
kev, n,
NULL, 0,
&ts);
if (ret == -1) {
log_error_write(ev->srv, __FILE__, __LINE__, "SS",
"kqueue event set failed: ", strerror(errno));
return -1;
}
return fd;
}
static int fdevent_freebsd_kqueue_event_get_revent(const fdevents *ev, size_t ndx) {
int events = 0;
int filt = ev->kq_results[ndx].filter;
int e = ev->kq_results[ndx].flags;
if (filt == EVFILT_READ) {
events |= FDEVENT_IN;
} else if (filt == EVFILT_WRITE) {
events |= FDEVENT_OUT;
}
if (e & EV_EOF) {
if (filt == EVFILT_READ) {
events |= FDEVENT_RDHUP;
} else {
events |= FDEVENT_HUP;
}
}
if (e & EV_ERROR) {
events |= FDEVENT_ERR;
}
return events;
return (0 != n) ? kevent(ev->kq_fd, kev, n, NULL, 0, &ts) : 0;
}
static int fdevent_freebsd_kqueue_poll(fdevents * const ev, int timeout_ms) {
@ -146,64 +78,37 @@ static int fdevent_freebsd_kqueue_poll(fdevents * const ev, int timeout_ms) {
for (int i = 0; i < n; ++i) {
fdnode * const fdn = ev->fdarray[ev->kq_results[i].ident];
int filt = ev->kq_results[i].filter;
int e = ev->kq_results[i].flags;
if (0 == ((uintptr_t)fdn & 0x3)) {
int revents = fdevent_freebsd_kqueue_event_get_revent(ev, i);
int revents = (filt == EVFILT_READ) ? FDEVENT_IN : FDEVENT_OUT;
if (e & EV_EOF)
revents |= (filt == EVFILT_READ ? FDEVENT_RDHUP : FDEVENT_HUP);
if (e & EV_ERROR)
revents |= FDEVENT_ERR;
(*fdn->handler)(srv, fdn->ctx, revents);
}
}
return n;
}
__attribute_cold__
static int fdevent_freebsd_kqueue_reset(fdevents *ev) {
if (-1 == (ev->kq_fd = kqueue())) {
log_error_write(ev->srv, __FILE__, __LINE__, "SSS",
"kqueue failed (", strerror(errno), "), try to set server.event-handler = \"poll\" or \"select\"");
return -1;
}
return 0;
return (-1 != (ev->kq_fd = kqueue())) ? 0 : -1;
}
__attribute_cold__
int fdevent_freebsd_kqueue_init(fdevents *ev) {
ev->type = FDEVENT_HANDLER_FREEBSD_KQUEUE;
#define SET(x) \
ev->x = fdevent_freebsd_kqueue_##x;
SET(free);
SET(poll);
SET(reset);
SET(event_del);
SET(event_set);
ev->kq_fd = -1;
ev->type = FDEVENT_HANDLER_FREEBSD_KQUEUE;
ev->event_set = fdevent_freebsd_kqueue_event_set;
ev->event_del = fdevent_freebsd_kqueue_event_del;
ev->poll = fdevent_freebsd_kqueue_poll;
ev->reset = fdevent_freebsd_kqueue_reset;
ev->free = fdevent_freebsd_kqueue_free;
ev->kq_fd = -1;
ev->kq_results = calloc(ev->maxfds, sizeof(*ev->kq_results));
force_assert(NULL != ev->kq_results);
/* check that kqueue works */
if (-1 == (ev->kq_fd = kqueue())) {
log_error_write(ev->srv, __FILE__, __LINE__, "SSS",
"kqueue failed (", strerror(errno), "), try to set server.event-handler = \"poll\" or \"select\"");
return -1;
}
close(ev->kq_fd);
ev->kq_fd = -1;
return 0;
}
#else
int fdevent_freebsd_kqueue_init(fdevents *ev) {
UNUSED(ev);
log_error_write(ev->srv, __FILE__, __LINE__, "S",
"kqueue not available, try to set server.event-handler = \"poll\" or \"select\"");
return -1;
}
#endif

12
src/fdevent_impl.h

@ -65,6 +65,7 @@ typedef struct _fdnode {
void *ctx;
int fd;
int events;
int fde_ndx;
#ifdef FDEVENT_USE_LIBEV
void *handler_ctx;
#endif
@ -88,8 +89,8 @@ struct fdevents {
fdnode **fdarray;
fdnode *pendclose;
int (*event_set)(struct fdevents *ev, int fde_ndx, int fd, int events);
int (*event_del)(struct fdevents *ev, int fde_ndx, int fd);
int (*event_set)(struct fdevents *ev, fdnode *fdn, int events);
int (*event_del)(struct fdevents *ev, fdnode *fdn);
int (*poll)(struct fdevents *ev, int timeout_ms);
struct server *srv;
@ -138,12 +139,19 @@ struct fdevents {
fdevent_handler_t type;
};
__attribute_cold__
int fdevent_select_init(struct fdevents *ev);
__attribute_cold__
int fdevent_poll_init(struct fdevents *ev);
__attribute_cold__
int fdevent_linux_sysepoll_init(struct fdevents *ev);
__attribute_cold__
int fdevent_solaris_devpoll_init(struct fdevents *ev);
__attribute_cold__
int fdevent_solaris_port_init(struct fdevents *ev);
__attribute_cold__
int fdevent_freebsd_kqueue_init(struct fdevents *ev);
__attribute_cold__
int fdevent_libev_init(struct fdevents *ev);
#endif

72
src/fdevent_libev.c

@ -5,7 +5,6 @@
#include "fdevent_impl.h"
#include "fdevent.h"
#include "buffer.h"
#include "log.h"
#ifdef FDEVENT_USE_LIBEV
@ -13,46 +12,38 @@
static void io_watcher_cb(struct ev_loop *loop, ev_io *w, int revents) {
fdevents *ev = w->data;
fdevent_handler handler = fdevent_get_handler(ev, w->fd);
void *context = fdevent_get_context(ev, w->fd);
fdnode *fdn = ev->fdarray[w->fd];
int r = 0;
UNUSED(loop);
if (NULL == handler) return;
if (revents & EV_READ) r |= FDEVENT_IN;
if (revents & EV_WRITE) r |= FDEVENT_OUT;
if (revents & EV_ERROR) r |= FDEVENT_ERR;
(*handler)(ev->srv, context, r);
if (0 == ((uintptr_t)fdn & 0x3)) {
(*fdn->handler)(ev->srv, fdn->ctx, r);
}
}
__attribute_cold__
static void fdevent_libev_free(fdevents *ev) {
UNUSED(ev);
}
static int fdevent_libev_event_del(fdevents *ev, int fde_ndx, int fd) {
fdnode *fdn;
ev_io *watcher;
if (-1 == fde_ndx) return -1;
fdn = ev->fdarray[fd];
watcher = fdn->handler_ctx;
if (!watcher) return -1;
static int fdevent_libev_event_del(fdevents *ev, fdnode *fdn) {
ev_io *watcher = fdn->handler_ctx;
if (!watcher) return 0;
fdn->handler_ctx = NULL;
ev_io_stop(ev->libev_loop, watcher);
free(watcher);
fdn->handler_ctx = NULL;
return -1;
return 0;
}
static int fdevent_libev_event_set(fdevents *ev, int fde_ndx, int fd, int events) {
fdnode *fdn = ev->fdarray[fd];
static int fdevent_libev_event_set(fdevents *ev, fdnode *fdn, int events) {
ev_io *watcher = fdn->handler_ctx;
int ev_events = 0;
UNUSED(fde_ndx);
if (events & FDEVENT_IN) ev_events |= EV_READ;
if (events & FDEVENT_OUT) ev_events |= EV_WRITE;
@ -60,8 +51,9 @@ static int fdevent_libev_event_set(fdevents *ev, int fde_ndx, int fd, int events
if (!watcher) {
fdn->handler_ctx = watcher = calloc(1, sizeof(ev_io));
force_assert(watcher);
fdn->fde_ndx = fdn->fd;
ev_io_init(watcher, io_watcher_cb, fd, ev_events);
ev_io_init(watcher, io_watcher_cb, fdn->fd, ev_events);
watcher->data = ev;
ev_io_start(ev->libev_loop, watcher);
} else {
@ -72,7 +64,7 @@ static int fdevent_libev_event_set(fdevents *ev, int fde_ndx, int fd, int events
}
}
return fd;
return 0;
}
static void timeout_watcher_cb(struct ev_loop *loop, ev_timer *w, int revents) {
@ -92,48 +84,30 @@ static int fdevent_libev_poll(fdevents *ev, int timeout_ms) {
return 0;
}
__attribute_cold__
static int fdevent_libev_reset(fdevents *ev) {
UNUSED(ev);
ev_default_fork();
return 0;
}
__attribute_cold__
int fdevent_libev_init(fdevents *ev) {
struct ev_timer * const timer = &timeout_watcher;
memset(timer, 0, sizeof(*timer));
ev->type = FDEVENT_HANDLER_LIBEV;
#define SET(x) \
ev->x = fdevent_libev_##x;
SET(free);
SET(poll);
SET(reset);
SET(event_del);
SET(event_set);
ev->type = FDEVENT_HANDLER_LIBEV;
ev->event_set = fdevent_libev_event_set;
ev->event_del = fdevent_libev_event_del;
ev->poll = fdevent_libev_poll;
ev->reset = fdevent_libev_reset;
ev->free = fdevent_libev_free;
if (NULL == (ev->libev_loop = ev_default_loop(0))) {
log_error_write(ev->srv, __FILE__, __LINE__, "S",
"ev_default_loop failed , try to set server.event-handler = \"poll\" or \"select\"");
return -1;
}
if (NULL == (ev->libev_loop = ev_default_loop(0))) return -1;
ev_timer_init(timer, timeout_watcher_cb, 0.0, 1.0);
return 0;
}
#else
int fdevent_libev_init(fdevents *ev) {
UNUSED(ev);
log_error_write(ev->srv, __FILE__, __LINE__, "S",
"libev not supported, try to set server.event-handler = \"poll\" or \"select\"");
return -1;
}
#endif

90
src/fdevent_linux_sysepoll.c

@ -3,76 +3,40 @@
#include "fdevent_impl.h"
#include "fdevent.h"
#include "buffer.h"
#include "log.h"
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#ifdef FDEVENT_USE_LINUX_EPOLL
# include <sys/epoll.h>
#ifndef EPOLLRDHUP
#define EPOLLRDHUP 0
#endif
__attribute_cold__
static void fdevent_linux_sysepoll_free(fdevents *ev) {
close(ev->epoll_fd);
free(ev->epoll_events);
}
static int fdevent_linux_sysepoll_event_del(fdevents *ev, int fde_ndx, int fd) {
if (fde_ndx < 0) return -1;
if (0 != epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, fd, NULL)) {
log_error_write(ev->srv, __FILE__, __LINE__, "SSS",
"epoll_ctl failed: ", strerror(errno), ", dying");
SEGFAULT();
return 0;
}
return -1;
static int fdevent_linux_sysepoll_event_del(fdevents *ev, fdnode *fdn) {
return epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, fdn->fd, NULL);
}
static int fdevent_linux_sysepoll_event_set(fdevents *ev, int fde_ndx, int fd, int events) {
struct epoll_event ep;
int add = (-1 == fde_ndx);
/**
*
* with EPOLLET we don't get a FDEVENT_HUP
* if the close is delay after everything has
* sent.
*
*/
ep.events = events | EPOLLERR | EPOLLHUP /* | EPOLLET */;
ep.data.fd = fd;
if (0 != epoll_ctl(ev->epoll_fd, add ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, fd, &ep)) {
log_error_write(ev->srv, __FILE__, __LINE__, "SSS",
"epoll_ctl failed: ", strerror(errno), ", dying");
SEGFAULT();
return 0;
}
return fd;
static int fdevent_linux_sysepoll_event_set(fdevents *ev, fdnode *fdn, int events) {
int op = (-1 == fdn->fde_ndx) ? EPOLL_CTL_ADD : EPOLL_CTL_MOD;
int fd = fdn->fde_ndx = fdn->fd;
struct epoll_event ep;
ep.events = events | EPOLLERR | EPOLLHUP;
ep.data.fd = fd;
return epoll_ctl(ev->epoll_fd, op, fd, &ep);
}
static int fdevent_linux_sysepoll_poll(fdevents * const ev, int timeout_ms) {
int n = epoll_wait(ev->epoll_fd, ev->epoll_events, ev->maxfds, timeout_ms);
server * const srv = ev->srv;
for (int i = 0; i < n; ++i) {
int revents = ev->epoll_events[i].events;
fdnode * const fdn = ev->fdarray[ev->epoll_events[i].data.fd];
int revents = ev->epoll_events[i].events;
if (0 == ((uintptr_t)fdn & 0x3)) {
(*fdn->handler)(srv, fdn->ctx, revents);
}
@ -80,31 +44,24 @@ static int fdevent_linux_sysepoll_poll(fdevents * const ev, int timeout_ms) {
return n;
}
__attribute_cold__
int fdevent_linux_sysepoll_init(fdevents *ev) {
ev->type = FDEVENT_HANDLER_LINUX_SYSEPOLL;
force_assert(EPOLLIN == FDEVENT_IN);
force_assert(EPOLLPRI == FDEVENT_PRI);
force_assert(EPOLLOUT == FDEVENT_OUT);
force_assert(EPOLLERR == FDEVENT_ERR);
force_assert(EPOLLHUP == FDEVENT_HUP);
#if 0 != EPOLLRDHUP
#ifdef EPOLLRDHUP
force_assert(EPOLLRDHUP == FDEVENT_RDHUP);
#endif
#define SET(x) \
ev->x = fdevent_linux_sysepoll_##x;
SET(free);
SET(poll);
SET(event_del);
SET(event_set);
ev->type = FDEVENT_HANDLER_LINUX_SYSEPOLL;
ev->event_set = fdevent_linux_sysepoll_event_set;
ev->event_del = fdevent_linux_sysepoll_event_del;
ev->poll = fdevent_linux_sysepoll_poll;
ev->free = fdevent_linux_sysepoll_free;
if (-1 == (ev->epoll_fd = epoll_create(ev->maxfds))) {
log_error_write(ev->srv, __FILE__, __LINE__, "SSS",
"epoll_create failed (", strerror(errno), "), try to set server.event-handler = \"poll\" or \"select\"");
return -1;
}
if (-1 == (ev->epoll_fd = epoll_create(ev->maxfds))) return -1;
fdevent_setfd_cloexec(ev->epoll_fd);
@ -114,13 +71,4 @@ int fdevent_linux_sysepoll_init(fdevents *ev) {
return 0;
}
#else
int fdevent_linux_sysepoll_init(fdevents *ev) {
UNUSED(ev);
log_error_write(ev->srv, __FILE__, __LINE__, "S",
"linux-sysepoll not supported, try to set server.event-handler = \"poll\" or \"select\"");
return -1;
}
#endif

83
src/fdevent_poll.c

@ -3,9 +3,6 @@
#include "fdevent_impl.h"
#include "fdevent.h"
#include "buffer.h"
#include "log.h"
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
@ -20,26 +17,16 @@
# include <sys/poll.h>
# endif
#ifndef POLLRDHUP
#define POLLRDHUP 0
#endif
__attribute_cold__
static void fdevent_poll_free(fdevents *ev) {
free(ev->pollfds);
if (ev->unused.ptr) free(ev->unused.ptr);
}
static int fdevent_poll_event_del(fdevents *ev, int fde_ndx, int fd) {
if (fde_ndx < 0) return -1;
if ((size_t)fde_ndx >= ev->used) {
log_error_write(ev->srv, __FILE__, __LINE__, "SdD",
"del! out of range ", fde_ndx, (int) ev->used);
SEGFAULT();
}
if (ev->pollfds[fde_ndx].fd == fd) {
size_t k = fde_ndx;
static int fdevent_poll_event_del(fdevents *ev, fdnode *fdn) {
int fd = fdn->fd;
int k = fdn->fde_ndx;
if ((size_t)k >= ev->used || ev->pollfds[k].fd != fd) return (errno = EINVAL, -1);
ev->pollfds[k].fd = -1;
/* ev->pollfds[k].events = 0; */
@ -52,28 +39,18 @@ static int fdevent_poll_event_del(fdevents *ev, int fde_ndx, int fd) {
}
ev->unused.ptr[ev->unused.used++] = k;
} else {
log_error_write(ev->srv, __FILE__, __LINE__, "SdD",
"del! ", ev->pollfds[fde_ndx].fd, fd);
SEGFAULT();
}
return -1;
return 0;
}
static int fdevent_poll_event_set(fdevents *ev, int fde_ndx, int fd, int events) {
int k;
if (fde_ndx != -1) {
if (ev->pollfds[fde_ndx].fd == fd) {
ev->pollfds[fde_ndx].events = events;
static int fdevent_poll_event_set(fdevents *ev, fdnode *fdn, int events) {
int fd = fdn->fd;
int k = fdn->fde_ndx;
return fde_ndx;
}
log_error_write(ev->srv, __FILE__, __LINE__, "SdD",
"set: ", fde_ndx, ev->pollfds[fde_ndx].fd);
SEGFAULT();
if (k >= 0) {
if ((size_t)k >= ev->used || ev->pollfds[k].fd != fd) return (errno = EINVAL, -1);
ev->pollfds[k].events = events;
return 0;
}
if (ev->unused.used > 0) {
@ -89,10 +66,11 @@ static int fdevent_poll_event_set(fdevents *ev, int fde_ndx, int fd, int events)
k = ev->used++;
}
fdn->fde_ndx = k;
ev->pollfds[k].fd = fd;
ev->pollfds[k].events = events;
return k;
return 0;
}
static int fdevent_poll_next_ndx(const fdevents *ev, int ndx) {
@ -106,8 +84,8 @@ static int fdevent_poll_poll(fdevents *ev, int timeout_ms) {
const int n = poll(ev->pollfds, ev->used, timeout_ms);
server * const srv = ev->srv;
for (int ndx=-1,i=0; i<n && -1!=(ndx=fdevent_poll_next_ndx(ev,ndx)); ++i){
int revents = ev->pollfds[ndx].revents;
fdnode *fdn = ev->fdarray[ev->pollfds[ndx].fd];
int revents = ev->pollfds[ndx].revents;
if (0 == ((uintptr_t)fdn & 0x3)) {
(*fdn->handler)(srv, fdn->ctx, revents);
}
@ -115,39 +93,24 @@ static int fdevent_poll_poll(fdevents *ev, int timeout_ms) {
return n;
}
__attribute_cold__
int fdevent_poll_init(fdevents *ev) {
ev->type = FDEVENT_HANDLER_POLL;
force_assert(POLLIN == FDEVENT_IN);
force_assert(POLLPRI == FDEVENT_PRI);
force_assert(POLLOUT == FDEVENT_OUT);
force_assert(POLLERR == FDEVENT_ERR);
force_assert(POLLHUP == FDEVENT_HUP);
force_assert(POLLNVAL == FDEVENT_NVAL);
#if 0 != POLLRDHUP
#ifdef POLLRDHUP
force_assert(POLLRDHUP == FDEVENT_RDHUP);
#endif
#define SET(x) \
ev->x = fdevent_poll_##x;
SET(free);
SET(poll);
SET(event_del);
SET(event_set);
ev->type = FDEVENT_HANDLER_POLL;
ev->event_set = fdevent_poll_event_set;
ev->event_del = fdevent_poll_event_del;
ev->poll = fdevent_poll_poll;
ev->free = fdevent_poll_free;
return 0;
}
#else
int fdevent_poll_init(fdevents *ev) {
UNUSED(ev);
log_error_write(ev->srv, __FILE__, __LINE__,
"s", "poll is not supported, try to set server.event-handler = \"select\"");
return -1;
}
#endif

62
src/fdevent_select.c

@ -3,39 +3,34 @@
#include "fdevent_impl.h"
#include "fdevent.h"
#include "buffer.h"
#include "log.h"
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#ifdef FDEVENT_USE_SELECT
__attribute_cold__
static int fdevent_select_reset(fdevents *ev) {
FD_ZERO(&(ev->select_set_read));
FD_ZERO(&(ev->select_set_write));
FD_ZERO(&(ev->select_set_error));
ev->select_max_fd = -1;
return 0;
}
static int fdevent_select_event_del(fdevents *ev, int fde_ndx, int fd) {
if (fde_ndx < 0) return -1;
static int fdevent_select_event_del(fdevents *ev, fdnode *fdn) {
int fd = fdn->fd;
FD_CLR(fd, &(ev->select_set_read));
FD_CLR(fd, &(ev->select_set_write));
FD_CLR(fd, &(ev->select_set_error));
return -1;
return 0;
}
static int fdevent_select_event_set(fdevents *ev, int fde_ndx, int fd, int events) {
UNUSED(fde_ndx);
static int fdevent_select_event_set(fdevents *ev, fdnode *fdn, int events) {
int fd = fdn->fde_ndx = fdn->fd;
/* we should be protected by max-fds, but you never know */
force_assert(fd < ((int)FD_SETSIZE));
@ -54,31 +49,20 @@ static int fdevent_select_event_set(fdevents *ev, int fde_ndx, int fd, int event
if (fd > ev->select_max_fd) ev->select_max_fd = fd;
return fd;
return 0;
}
static int fdevent_select_event_get_revent(const fdevents *ev, size_t ndx) {
int revents = 0;
if (FD_ISSET(ndx, &(ev->select_read))) {
revents |= FDEVENT_IN;
}
if (FD_ISSET(ndx, &(ev->select_write))) {
revents |= FDEVENT_OUT;
}
if (FD_ISSET(ndx, &(ev->select_error))) {
revents |= FDEVENT_ERR;
}
if (FD_ISSET(ndx, &ev->select_read)) revents |= FDEVENT_IN;
if (FD_ISSET(ndx, &ev->select_write)) revents |= FDEVENT_OUT;
if (FD_ISSET(ndx, &ev->select_error)) revents |= FDEVENT_ERR;
return revents;
}
static int fdevent_select_event_next_fdndx(const fdevents *ev, int ndx) {
int i;
i = (ndx < 0) ? 0 : ndx + 1;
for (; i < ev->select_max_fd + 1; i++) {
const int max_fd = ev->select_max_fd + 1;
for (int i = (ndx < 0) ? 0 : ndx + 1; i < max_fd; ++i) {
if (FD_ISSET(i, &(ev->select_read))) return i;
if (FD_ISSET(i, &(ev->select_write))) return i;
if (FD_ISSET(i, &(ev->select_error))) return i;
@ -112,24 +96,14 @@ static int fdevent_select_poll(fdevents *ev, int timeout_ms) {
return n;
}
__attribute_cold__
int fdevent_select_init(fdevents *ev) {
ev->type = FDEVENT_HANDLER_SELECT;
#define SET(x) \
ev->x = fdevent_select_##x;
SET(reset);
SET(poll);
SET(event_del);
SET(event_set);
ev->type = FDEVENT_HANDLER_SELECT;
ev->event_set = fdevent_select_event_set;
ev->event_del = fdevent_select_event_del;
ev->poll = fdevent_select_poll;
ev->reset = fdevent_select_reset;
return 0;
}
#else
int fdevent_select_init(fdevents *ev) {
UNUSED(ev);
return -1;
}
#endif

90
src/fdevent_solaris_devpoll.c

@ -3,14 +3,10 @@
#include "fdevent_impl.h"
#include "fdevent.h"
#include "buffer.h"
#include "log.h"
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#ifdef FDEVENT_USE_SOLARIS_DEVPOLL
@ -18,6 +14,7 @@
# include <sys/devpoll.h>
# include <sys/ioctl.h>
__attribute_cold__
static void fdevent_solaris_devpoll_free(fdevents *ev) {
free(ev->devpollfds);
close(ev->devpoll_fd);
@ -25,41 +22,20 @@ static void fdevent_solaris_devpoll_free(fdevents *ev) {
/* return -1 is fine here */
static int fdevent_solaris_devpoll_event_del(fdevents *ev, int fde_ndx, int fd) {
static int fdevent_solaris_devpoll_event_del(fdevents *ev, fdnode *fdn) {
struct pollfd pfd;
if (fde_ndx < 0) return -1;
pfd.fd = fd;
pfd.fd = fdn->fd;
pfd.events = POLLREMOVE;
pfd.revents = 0;
if (-1 == write(ev->devpoll_fd, &pfd, sizeof(pfd))) {
log_error_write(ev->srv, __FILE__, __LINE__, "S(D, S)",
"(del) write failed: ", fd, strerror(errno));
return -1;
}
return -1;
return (-1 != write(ev->devpoll_fd, &pfd, sizeof(pfd))) ? 0 : -1;
}
static int fdevent_solaris_devpoll_event_set(fdevents *ev, int fde_ndx, int fd, int events) {
static int fdevent_solaris_devpoll_event_set(fdevents *ev, fdnode *fdn, int events) {
struct pollfd pfd;
int add = (-1 == fde_ndx);
pfd.fd = fd;
pfd.fd = fdn->fde_ndx = fdn->fd;
pfd.events = events;
pfd.revents = 0;
if (-1 == write(ev->devpoll_fd, &pfd, sizeof(pfd))) {
log_error_write(ev->srv, __FILE__, __LINE__, "S(D, S)",
"(set) write failed: ", fd, strerror(errno));
return -1;
}
return fd;
return (-1 != write(ev->devpoll_fd, &pfd, sizeof(pfd))) ? 0 : -1;
}
static int fdevent_solaris_devpoll_poll(fdevents *ev, int timeout_ms) {
@ -74,8 +50,8 @@ static int fdevent_solaris_devpoll_poll(fdevents *ev, int timeout_ms) {
n = ioctl(ev->devpoll_fd, DP_POLL, &dopoll);
for (int i = 0; i < n; ++i) {
int revents = ev->devpollfds[i].revents;
fdnode * const fdn = ev->fdarray[ev->devpollfds[i].fd];
int revents = ev->devpollfds[i].revents;
if (0 == ((uintptr_t)fdn & 0x3)) {
(*fdn->handler)(srv, fdn->ctx, revents);
}
@ -83,21 +59,17 @@ static int fdevent_solaris_devpoll_poll(fdevents *ev, int timeout_ms) {
return n;
}
__attribute_cold__
int fdevent_solaris_devpoll_reset(fdevents *ev) {
/* a forked process does only inherit the filedescriptor,
* but every operation on the device will lead to a EACCES */
if ((ev->devpoll_fd = open("/dev/poll", O_RDWR)) < 0) {
log_error_write(ev->srv, __FILE__, __LINE__, "SSS",
"opening /dev/poll failed (", strerror(errno), "), try to set server.event-handler = \"poll\" or \"select\"");
return -1;
}
if ((ev->devpoll_fd = open("/dev/poll", O_RDWR)) < 0) return -1;
fdevent_setfd_cloexec(ev->devpoll_fd);
return 0;
}
__attribute_cold__
int fdevent_solaris_devpoll_init(fdevents *ev) {
ev->type = FDEVENT_HANDLER_SOLARIS_DEVPOLL;
force_assert(POLLIN == FDEVENT_IN);
force_assert(POLLPRI == FDEVENT_PRI);
force_assert(POLLOUT == FDEVENT_OUT);
@ -105,41 +77,17 @@ int fdevent_solaris_devpoll_init(fdevents *ev) {
force_assert(POLLHUP == FDEVENT_HUP);
force_assert(POLLNVAL == FDEVENT_NVAL);
force_assert(POLLRDHUP == FDEVENT_RDHUP);
#define SET(x) \
ev->x = fdevent_solaris_devpoll_##x;
SET(free);
SET(poll);
SET(reset);
SET(event_del);
SET(event_set);
ev->type = FDEVENT_HANDLER_SOLARIS_DEVPOLL;
ev->event_set = fdevent_solaris_devpoll_event_set;
ev->event_del = fdevent_solaris_devpoll_event_del;
ev->poll = fdevent_solaris_devpoll_poll;
ev->reset = fdevent_solaris_devpoll_reset;
ev->free = fdevent_solaris_devpoll_free;
ev->devpoll_fd = -1;
ev->devpollfds = malloc(sizeof(*ev->devpollfds) * ev->maxfds);
force_assert(NULL != ev->devpollfds);
if ((ev->devpoll_fd = open("/dev/poll", O_RDWR)) < 0) {
log_error_write(ev->srv, __FILE__, __LINE__, "SSS",
"opening /dev/poll failed (", strerror(errno), "), try to set server.event-handler = \"poll\" or \"select\"");
return -1;
}
/* we just wanted to check if it works */
close(ev->devpoll_fd);
ev->devpoll_fd = -1;
return 0;
}
#else
int fdevent_solaris_devpoll_init(fdevents *ev) {
UNUSED(ev);
log_error_write(ev->srv, __FILE__, __LINE__, "S",
"solaris-devpoll not supported, try to set server.event-handler = \"poll\" or \"select\"");
return -1;
}
#endif

113
src/fdevent_solaris_port.c

@ -5,8 +5,6 @@
#include "buffer.h"
#include "log.h"
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
@ -16,48 +14,18 @@
#ifdef FDEVENT_USE_SOLARIS_PORT
#include <sys/poll.h>
static const int SOLARIS_PORT_POLL_READ = POLLIN;
static const int SOLARIS_PORT_POLL_WRITE = POLLOUT;
static const int SOLARIS_PORT_POLL_READ_WRITE = POLLIN & POLLOUT;
static int fdevent_solaris_port_event_del(fdevents *ev, int fde_ndx, int fd) {
if (fde_ndx < 0) return -1;
if (0 != port_dissociate(ev->port_fd, PORT_SOURCE_FD, fd)) {
log_error_write(ev->srv, __FILE__, __LINE__, "SSS",
"port_dissociate failed: ", strerror(errno), ", dying");
SEGFAULT();
return 0;
}
return -1;
static int fdevent_solaris_port_event_del(fdevents *ev, fdnode *fdn) {
return port_dissociate(ev->port_fd, PORT_SOURCE_FD, fdn->fd);
}
static int fdevent_solaris_port_event_set(fdevents *ev, int fde_ndx, int fd, int events) {
const int* user_data = NULL;
if ((events & FDEVENT_IN) && (events & FDEVENT_OUT)) {
user_data = &SOLARIS_PORT_POLL_READ_WRITE;
} else if (events & FDEVENT_IN) {
user_data = &SOLARIS_PORT_POLL_READ;
} else if (events & FDEVENT_OUT) {
user_data = &SOLARIS_PORT_POLL_WRITE;
}
if (0 != port_associate(ev->port_fd, PORT_SOURCE_FD, fd, *user_data, (void*) user_data)) {
log_error_write(ev->srv, __FILE__, __LINE__, "SSS",
"port_associate failed: ", strerror(errno), ", dying");
SEGFAULT();
return 0;
}
return fd;
static int fdevent_solaris_port_event_set(fdevents *ev, fdnode *fdn, int events) {
int fd = fdn->fdn_ndx = fdn->fd;
intptr_t ud = events & (POLLIN|POLLOUT);
return port_associate(ev->port_fd,PORT_SOURCE_FD,fd,(int)ud,(void*)ud);
}
__attribute_cold__
static void fdevent_solaris_port_free(fdevents *ev) {
close(ev->port_fd);
free(ev->port_events);
@ -65,10 +33,9 @@ static void fdevent_solaris_port_free(fdevents *ev) {
/* if there is any error it will return the return values of port_getn, otherwise it will return number of events **/
static int fdevent_solaris_port_poll(fdevents *ev, int timeout_ms) {
int i = 0;
const int pfd = ev->port_fd;
int ret;
unsigned int available_events, wait_for_events = 0;
const int *user_data;
struct timespec timeout;
@ -76,7 +43,7 @@ static int fdevent_solaris_port_poll(fdevents *ev, int timeout_ms) {
timeout.tv_nsec = (timeout_ms % 1000L) * 1000000L;
/* get the number of file descriptors with events */
if ((ret = port_getn(ev->port_fd, ev->port_events, 0, &wait_for_events, &timeout)) < 0) return ret;
if ((ret = port_getn(pfd, ev->port_events, 0, &wait_for_events, &timeout)) < 0) return ret;
/* wait for at least one event */
if (0 == wait_for_events) wait_for_events = 1;
@ -84,38 +51,33 @@ static int fdevent_solaris_port_poll(fdevents *ev, int timeout_ms) {
available_events = wait_for_events;
/* get the events of the file descriptors */
if ((ret = port_getn(ev->port_fd, ev->port_events, ev->maxfds, &available_events, &timeout)) < 0) {
if ((ret = port_getn(pfd, ev->port_events, ev->maxfds, &available_events, &timeout)) < 0) {
/* if errno == ETIME and available_event == wait_for_events we didn't get any events */
/* for other errors we didn't get any events either */
if (!(errno == ETIME && wait_for_events != available_events)) return ret;
}
for (i = 0; i < (int)available_events; ++i) {
user_data = (const int *) ev->port_events[i].portev_user;
if ((ret = port_associate(ev->port_fd, PORT_SOURCE_FD, ev->port_events[i].portev_object,
*user_data, (void*) user_data)) < 0) {
log_error_write(ev->srv, __FILE__, __LINE__, "SSS",
"port_associate failed: ", strerror(errno), ", dying");
SEGFAULT();
return 0;
}
}
for (i = 0; i < available_events; ++i) {
for (int i = 0; i < (int)available_events; ++i) {
int fd = (int)ev->port_events[i].portev_object;
fdnode * const fdn = ev->fdarray[fd];
const intptr_t ud = (intptr_t)ev->port_events[i].portev_user;
int revents = ev->port_events[i].portev_events;
fdnode * const fdn = ev->fdarray[ev->port_events[i].portev_object];
if (0 == ((uintptr_t)fdn & 0x3)) {
if (port_associate(pfd,PORT_SOURCE_FD,fd,(int)ud,(void*)ud) < 0) {
log_error_write(ev->srv, __FILE__, __LINE__, "SS",
"port_associate failed: ", strerror(errno));
}
(*fdn->handler)(ev->srv, fdn->ctx, revents);
}
else {
fdn->fde_ndx = -1;
}
}
return available_events;
}
__attribute_cold__
int fdevent_solaris_port_init(fdevents *ev) {
ev->type = FDEVENT_HANDLER_SOLARIS_PORT;
force_assert(POLLIN == FDEVENT_IN);
force_assert(POLLPRI == FDEVENT_PRI);
force_assert(POLLOUT == FDEVENT_OUT);
@ -123,35 +85,18 @@ int fdevent_solaris_port_init(fdevents *ev) {
force_assert(POLLHUP == FDEVENT_HUP);
force_assert(POLLNVAL == FDEVENT_NVAL);
force_assert(POLLRDHUP == FDEVENT_RDHUP);
#define SET(x) \
ev->x = fdevent_solaris_port_##x;
SET(free);
SET(poll);
SET(event_del);