summaryrefslogtreecommitdiffhomepage
path: root/src/nxt_devpoll.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nxt_devpoll.c')
-rw-r--r--src/nxt_devpoll.c699
1 files changed, 0 insertions, 699 deletions
diff --git a/src/nxt_devpoll.c b/src/nxt_devpoll.c
deleted file mode 100644
index 8fbe8184..00000000
--- a/src/nxt_devpoll.c
+++ /dev/null
@@ -1,699 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) NGINX, Inc.
- */
-
-#include <nxt_main.h>
-
-
-/*
- * "/dev/poll" has been introduced in Solaris 7 (11/99), HP-UX 11.22 (named
- * "eventport pseudo driver" internally, not to be confused with Solaris 10
- * event ports), IRIX 6.5.15, and Tru64 UNIX 5.1A.
- *
- * Although "/dev/poll" descriptor is a file descriptor, nevertheless
- * it cannot be added to another poll set, Solaris poll(7d):
- *
- * The /dev/poll driver does not yet support polling. Polling on a
- * /dev/poll file descriptor will result in POLLERR being returned
- * in the revents field of pollfd structure.
- */
-
-
-#define NXT_DEVPOLL_ADD 0
-#define NXT_DEVPOLL_UPDATE 1
-#define NXT_DEVPOLL_CHANGE 2
-#define NXT_DEVPOLL_DELETE 3
-
-
-static nxt_event_set_t *nxt_devpoll_create(nxt_event_signals_t *signals,
- nxt_uint_t mchanges, nxt_uint_t mevents);
-static void nxt_devpoll_free(nxt_event_set_t *event_set);
-static void nxt_devpoll_enable(nxt_event_set_t *event_set, nxt_event_fd_t *ev);
-static void nxt_devpoll_disable(nxt_event_set_t *event_set, nxt_event_fd_t *ev);
-#if (NXT_HPUX)
-static void nxt_devpoll_close(nxt_event_set_t *event_set, nxt_event_fd_t *ev);
-static void nxt_devpoll_drop_changes(nxt_event_set_t *event_set,
- nxt_event_fd_t *ev);
-#endif
-static void nxt_devpoll_enable_read(nxt_event_set_t *event_set,
- nxt_event_fd_t *ev);
-static void nxt_devpoll_enable_write(nxt_event_set_t *event_set,
- nxt_event_fd_t *ev);
-static void nxt_devpoll_disable_read(nxt_event_set_t *event_set,
- nxt_event_fd_t *ev);
-static void nxt_devpoll_disable_write(nxt_event_set_t *event_set,
- nxt_event_fd_t *ev);
-static void nxt_devpoll_block_read(nxt_event_set_t *event_set,
- nxt_event_fd_t *ev);
-static void nxt_devpoll_block_write(nxt_event_set_t *event_set,
- nxt_event_fd_t *ev);
-static void nxt_devpoll_oneshot_read(nxt_event_set_t *event_set,
- nxt_event_fd_t *ev);
-static void nxt_devpoll_oneshot_write(nxt_event_set_t *event_set,
- nxt_event_fd_t *ev);
-static void nxt_devpoll_change(nxt_event_set_t *event_set, nxt_event_fd_t *ev,
- nxt_uint_t op, nxt_uint_t events);
-static nxt_int_t nxt_devpoll_commit_changes(nxt_thread_t *thr,
- nxt_devpoll_event_set_t *ds);
-static void nxt_devpoll_change_error(nxt_thread_t *thr,
- nxt_devpoll_event_set_t *ds, nxt_event_fd_t *ev);
-static void nxt_devpoll_remove(nxt_thread_t *thr, nxt_devpoll_event_set_t *ds,
- nxt_fd_t fd);
-static nxt_int_t nxt_devpoll_write(nxt_thread_t *thr, int devpoll,
- struct pollfd *pfd, size_t n);
-static void nxt_devpoll_set_poll(nxt_thread_t *thr, nxt_event_set_t *event_set,
- nxt_msec_t timeout);
-
-
-const nxt_event_set_ops_t nxt_devpoll_event_set = {
- "devpoll",
- nxt_devpoll_create,
- nxt_devpoll_free,
- nxt_devpoll_enable,
- nxt_devpoll_disable,
- nxt_devpoll_disable,
-#if (NXT_HPUX)
- nxt_devpoll_close,
-#else
- nxt_devpoll_disable,
-#endif
- nxt_devpoll_enable_read,
- nxt_devpoll_enable_write,
- nxt_devpoll_disable_read,
- nxt_devpoll_disable_write,
- nxt_devpoll_block_read,
- nxt_devpoll_block_write,
- nxt_devpoll_oneshot_read,
- nxt_devpoll_oneshot_write,
- nxt_devpoll_enable_read,
- NULL,
- NULL,
- NULL,
- NULL,
- nxt_devpoll_set_poll,
-
- &nxt_unix_event_conn_io,
-
- NXT_NO_FILE_EVENTS,
- NXT_NO_SIGNAL_EVENTS,
-};
-
-
-static nxt_event_set_t *
-nxt_devpoll_create(nxt_event_signals_t *signals, nxt_uint_t mchanges,
- nxt_uint_t mevents)
-{
- nxt_event_set_t *event_set;
- nxt_devpoll_event_set_t *ds;
-
- event_set = nxt_zalloc(sizeof(nxt_devpoll_event_set_t));
- if (event_set == NULL) {
- return NULL;
- }
-
- ds = &event_set->devpoll;
-
- ds->devpoll = -1;
- ds->mchanges = mchanges;
- ds->mevents = mevents;
-
- ds->devpoll_changes = nxt_malloc(sizeof(nxt_devpoll_change_t) * mchanges);
- if (ds->devpoll_changes == NULL) {
- goto fail;
- }
-
- /*
- * NXT_DEVPOLL_CHANGE requires two struct pollfd's:
- * for POLLREMOVE and subsequent POLLIN or POLLOUT.
- */
- ds->changes = nxt_malloc(2 * sizeof(struct pollfd) * mchanges);
- if (ds->changes == NULL) {
- goto fail;
- }
-
- ds->events = nxt_malloc(sizeof(struct pollfd) * mevents);
- if (ds->events == NULL) {
- goto fail;
- }
-
- ds->devpoll = open("/dev/poll", O_RDWR);
- if (ds->devpoll == -1) {
- nxt_main_log_emerg("open(/dev/poll) failed %E", nxt_errno);
- goto fail;
- }
-
- nxt_main_log_debug("open(/dev/poll): %d", ds->devpoll);
-
- return event_set;
-
-fail:
-
- nxt_devpoll_free(event_set);
-
- return NULL;
-}
-
-
-static void
-nxt_devpoll_free(nxt_event_set_t *event_set)
-{
- nxt_devpoll_event_set_t *ds;
-
- ds = &event_set->devpoll;
-
- nxt_main_log_debug("devpoll %d free", ds->devpoll);
-
- if (ds->devpoll != -1) {
- if (close(ds->devpoll) != 0) {
- nxt_main_log_emerg("devpoll close(%d) failed %E",
- ds->devpoll, nxt_errno);
- }
- }
-
- nxt_free(ds->events);
- nxt_free(ds->changes);
- nxt_free(ds->devpoll_changes);
- nxt_event_set_fd_hash_destroy(&ds->fd_hash);
- nxt_free(ds);
-}
-
-
-static void
-nxt_devpoll_enable(nxt_event_set_t *event_set, nxt_event_fd_t *ev)
-{
- ev->read = NXT_EVENT_DEFAULT;
- ev->write = NXT_EVENT_DEFAULT;
-
- nxt_devpoll_change(event_set, ev, NXT_DEVPOLL_ADD, POLLIN | POLLOUT);
-}
-
-
-/*
- * Solaris does not automatically remove a closed file descriptor from
- * a "/dev/poll" set: ioctl(DP_ISPOLLED) for the descriptor returns 1,
- * significative of active descriptor. POLLREMOVE can remove already
- * closed file descriptor, so the removal can be batched, Solaris poll(7d):
- *
- * When using the "/dev/poll" driver, you should remove a closed file
- * descriptor from a monitored poll set. Failure to do so may result
- * in a POLLNVAL revents being returned for the closed file descriptor.
- * When a file descriptor is closed but not removed from the monitored
- * set, and is reused in subsequent open of a different device, you
- * will be polling the device associated with the reused file descriptor.
- * In a multithreaded application, careful coordination among threads
- * doing close and DP_POLL ioctl is recommended for consistent results.
- *
- * Besides Solaris and HP-UX allow to add invalid descriptors to an
- * "/dev/poll" set, although the descriptors are not marked as polled,
- * that is, ioctl(DP_ISPOLLED) returns 0.
- */
-
-static void
-nxt_devpoll_disable(nxt_event_set_t *event_set, nxt_event_fd_t *ev)
-{
- if (ev->read != NXT_EVENT_INACTIVE || ev->write != NXT_EVENT_INACTIVE) {
-
- ev->read = NXT_EVENT_INACTIVE;
- ev->write = NXT_EVENT_INACTIVE;
-
- nxt_devpoll_change(event_set, ev, NXT_DEVPOLL_DELETE, POLLREMOVE);
- }
-}
-
-
-#if (NXT_HPUX)
-
-/*
- * HP-UX poll(7):
- *
- * When a polled file descriptor is closed, it is automatically
- * deregistered.
- */
-
-static void
-nxt_devpoll_close(nxt_event_set_t *event_set, nxt_event_fd_t *ev)
-{
- ev->read = NXT_EVENT_INACTIVE;
- ev->write = NXT_EVENT_INACTIVE;
-
- nxt_devpoll_drop_changes(event_set, ev);
-}
-
-
-static void
-nxt_devpoll_drop_changes(nxt_event_set_t *event_set, nxt_event_fd_t *ev)
-{
- nxt_devpoll_change_t *dst, *src, *end;
- nxt_devpoll_event_set_t *ds;
-
- ds = &event_set->devpoll;
-
- dst = ds->devpoll_changes;
- end = dst + ds->nchanges;
-
- for (src = dst; src < end; src++) {
-
- if (src->event == ev) {
- continue;
- }
-
- if (dst != src) {
- *dst = *src;
- }
-
- dst++;
- }
-
- ds->nchanges -= end - dst;
-}
-
-#endif
-
-
-/*
- * Solaris poll(7d):
- *
- * The fd field specifies the file descriptor being polled. The events
- * field indicates the interested poll events on the file descriptor.
- * If a pollfd array contains multiple pollfd entries with the same fd field,
- * the "events" field in each pollfd entry is OR'ed. A special POLLREMOVE
- * event in the events field of the pollfd structure removes the fd from
- * the monitored set. The revents field is not used.
- */
-
-static void
-nxt_devpoll_enable_read(nxt_event_set_t *event_set, nxt_event_fd_t *ev)
-{
- nxt_uint_t op, events;
-
- if (ev->read != NXT_EVENT_BLOCKED) {
-
- events = POLLIN;
-
- if (ev->write == NXT_EVENT_INACTIVE) {
- op = NXT_DEVPOLL_ADD;
-
- } else if (ev->write == NXT_EVENT_BLOCKED) {
- ev->write = NXT_EVENT_INACTIVE;
- op = NXT_DEVPOLL_CHANGE;
-
- } else {
- op = NXT_DEVPOLL_UPDATE;
- events = POLLIN | POLLOUT;
- }
-
- nxt_devpoll_change(event_set, ev, op, events);
- }
-
- ev->read = NXT_EVENT_DEFAULT;
-}
-
-
-static void
-nxt_devpoll_enable_write(nxt_event_set_t *event_set, nxt_event_fd_t *ev)
-{
- nxt_uint_t op, events;
-
- if (ev->write != NXT_EVENT_BLOCKED) {
-
- events = POLLOUT;
-
- if (ev->read == NXT_EVENT_INACTIVE) {
- op = NXT_DEVPOLL_ADD;
-
- } else if (ev->read == NXT_EVENT_BLOCKED) {
- ev->read = NXT_EVENT_INACTIVE;
- op = NXT_DEVPOLL_CHANGE;
-
- } else {
- op = NXT_DEVPOLL_UPDATE;
- events = POLLIN | POLLOUT;
- }
-
- nxt_devpoll_change(event_set, ev, op, events);
- }
-
- ev->write = NXT_EVENT_DEFAULT;
-}
-
-
-static void
-nxt_devpoll_disable_read(nxt_event_set_t *event_set, nxt_event_fd_t *ev)
-{
- nxt_uint_t op, events;
-
- ev->read = NXT_EVENT_INACTIVE;
-
- if (ev->write <= NXT_EVENT_BLOCKED) {
- ev->write = NXT_EVENT_INACTIVE;
- op = NXT_DEVPOLL_DELETE;
- events = POLLREMOVE;
-
- } else {
- op = NXT_DEVPOLL_CHANGE;
- events = POLLOUT;
- }
-
- nxt_devpoll_change(event_set, ev, op, events);
-}
-
-
-static void
-nxt_devpoll_disable_write(nxt_event_set_t *event_set, nxt_event_fd_t *ev)
-{
- nxt_uint_t op, events;
-
- ev->write = NXT_EVENT_INACTIVE;
-
- if (ev->read <= NXT_EVENT_BLOCKED) {
- ev->read = NXT_EVENT_INACTIVE;
- op = NXT_DEVPOLL_DELETE;
- events = POLLREMOVE;
-
- } else {
- op = NXT_DEVPOLL_CHANGE;
- events = POLLIN;
- }
-
- nxt_devpoll_change(event_set, ev, op, events);
-}
-
-
-static void
-nxt_devpoll_block_read(nxt_event_set_t *event_set, nxt_event_fd_t *ev)
-{
- if (ev->read != NXT_EVENT_INACTIVE) {
- ev->read = NXT_EVENT_BLOCKED;
- }
-}
-
-
-static void
-nxt_devpoll_block_write(nxt_event_set_t *event_set, nxt_event_fd_t *ev)
-{
- if (ev->write != NXT_EVENT_INACTIVE) {
- ev->write = NXT_EVENT_BLOCKED;
- }
-}
-
-
-static void
-nxt_devpoll_oneshot_read(nxt_event_set_t *event_set, nxt_event_fd_t *ev)
-{
- nxt_devpoll_enable_read(event_set, ev);
-
- ev->read = NXT_EVENT_ONESHOT;
-}
-
-
-static void
-nxt_devpoll_oneshot_write(nxt_event_set_t *event_set, nxt_event_fd_t *ev)
-{
- nxt_devpoll_enable_write(event_set, ev);
-
- ev->write = NXT_EVENT_ONESHOT;
-}
-
-
-static void
-nxt_devpoll_change(nxt_event_set_t *event_set, nxt_event_fd_t *ev,
- nxt_uint_t op, nxt_uint_t events)
-{
- nxt_devpoll_change_t *ch;
- nxt_devpoll_event_set_t *ds;
-
- ds = &event_set->devpoll;
-
- nxt_log_debug(ev->log, "devpoll %d change fd:%d op:%ui ev:%04Xi",
- ds->devpoll, ev->fd, op, events);
-
- if (ds->nchanges >= ds->mchanges) {
- (void) nxt_devpoll_commit_changes(nxt_thread(), ds);
- }
-
- ch = &ds->devpoll_changes[ds->nchanges++];
- ch->op = op;
- ch->fd = ev->fd;
- ch->events = events;
- ch->event = ev;
-}
-
-
-static nxt_int_t
-nxt_devpoll_commit_changes(nxt_thread_t *thr, nxt_devpoll_event_set_t *ds)
-{
- size_t n;
- nxt_int_t ret, retval;
- struct pollfd *pfd;
- nxt_devpoll_change_t *ch, *end;
-
- nxt_log_debug(thr->log, "devpoll %d changes:%ui",
- ds->devpoll, ds->nchanges);
-
- retval = NXT_OK;
- n = 0;
- ch = ds->devpoll_changes;
- end = ch + ds->nchanges;
-
- do {
- nxt_log_debug(thr->log, "devpoll fd:%d op:%d ev:%04Xd",
- ch->fd, ch->op, ch->events);
-
- if (ch->op == NXT_DEVPOLL_CHANGE) {
- pfd = &ds->changes[n++];
- pfd->fd = ch->fd;
- pfd->events = POLLREMOVE;
- pfd->revents = 0;
- }
-
- pfd = &ds->changes[n++];
- pfd->fd = ch->fd;
- pfd->events = ch->events;
- pfd->revents = 0;
-
- ch++;
-
- } while (ch < end);
-
- ch = ds->devpoll_changes;
- end = ch + ds->nchanges;
-
- ret = nxt_devpoll_write(thr, ds->devpoll, ds->changes, n);
-
- if (nxt_slow_path(ret != NXT_OK)) {
- do {
- nxt_devpoll_change_error(thr, ds, ch->event);
- ch++;
- } while (ch < end);
-
- ds->nchanges = 0;
-
- return NXT_ERROR;
- }
-
- do {
- if (ch->op == NXT_DEVPOLL_ADD) {
- ret = nxt_event_set_fd_hash_add(&ds->fd_hash, ch->fd, ch->event);
-
- if (nxt_slow_path(ret != NXT_OK)) {
- nxt_devpoll_change_error(thr, ds, ch->event);
- retval = NXT_ERROR;
- }
-
- } else if (ch->op == NXT_DEVPOLL_DELETE) {
- nxt_event_set_fd_hash_delete(&ds->fd_hash, ch->fd, 0);
- }
-
- /* Nothing tp do for NXT_DEVPOLL_UPDATE and NXT_DEVPOLL_CHANGE. */
-
- ch++;
-
- } while (ch < end);
-
- ds->nchanges = 0;
-
- return retval;
-}
-
-
-static void
-nxt_devpoll_change_error(nxt_thread_t *thr, nxt_devpoll_event_set_t *ds,
- nxt_event_fd_t *ev)
-{
- ev->read = NXT_EVENT_INACTIVE;
- ev->write = NXT_EVENT_INACTIVE;
-
- nxt_thread_work_queue_add(thr, &thr->work_queue.main,
- ev->error_handler, ev, ev->data, ev->log);
-
- nxt_event_set_fd_hash_delete(&ds->fd_hash, ev->fd, 1);
-
- nxt_devpoll_remove(thr, ds, ev->fd);
-}
-
-
-static void
-nxt_devpoll_remove(nxt_thread_t *thr, nxt_devpoll_event_set_t *ds, nxt_fd_t fd)
-{
- int n;
- struct pollfd pfd;
-
- pfd.fd = fd;
- pfd.events = 0;
- pfd.revents = 0;
-
- n = ioctl(ds->devpoll, DP_ISPOLLED, &pfd);
-
- nxt_log_debug(thr->log, "ioctl(%d, DP_ISPOLLED, %d): %d",
- ds->devpoll, fd, n);
-
- if (n == 0) {
- /* The file descriptor is not in the set. */
- return;
- }
-
- if (n == -1) {
- nxt_log_alert(thr->log, "ioctl(%d, DP_ISPOLLED, %d) failed %E",
- ds->devpoll, fd, nxt_errno);
- /* Fall through. */
- }
-
- /* n == 1: the file descriptor is in the set. */
-
- nxt_log_debug(thr->log, "devpoll %d remove fd:%d", ds->devpoll, fd);
-
- pfd.fd = fd;
- pfd.events = POLLREMOVE;
- pfd.revents = 0;
-
- nxt_devpoll_write(thr, ds->devpoll, &pfd, 1);
-}
-
-
-static nxt_int_t
-nxt_devpoll_write(nxt_thread_t *thr, int devpoll, struct pollfd *pfd,
- size_t n)
-{
- nxt_log_debug(thr->log, "devpoll write(%d) changes:%uz", devpoll, n);
-
- n *= sizeof(struct pollfd);
-
- if (nxt_slow_path(write(devpoll, pfd, n) == (ssize_t) n)) {
- return NXT_OK;
- }
-
- nxt_log_alert(thr->log, "devpoll write(%d) failed %E",
- devpoll, nxt_errno);
-
- return NXT_ERROR;
-}
-
-
-static void
-nxt_devpoll_set_poll(nxt_thread_t *thr, nxt_event_set_t *event_set,
- nxt_msec_t timeout)
-{
- int nevents;
- nxt_fd_t fd;
- nxt_int_t i;
- nxt_err_t err;
- nxt_uint_t events, level;
- struct dvpoll dvp;
- struct pollfd *pfd;
- nxt_event_fd_t *ev;
- nxt_devpoll_event_set_t *ds;
-
- ds = &event_set->devpoll;
-
- if (ds->nchanges != 0) {
- if (nxt_devpoll_commit_changes(thr, ds) != NXT_OK) {
- /* Error handlers have been enqueued on failure. */
- timeout = 0;
- }
- }
-
- nxt_log_debug(thr->log, "ioctl(%d, DP_POLL) timeout:%M",
- ds->devpoll, timeout);
-
- dvp.dp_fds = ds->events;
- dvp.dp_nfds = ds->mevents;
- dvp.dp_timeout = timeout;
-
- nevents = ioctl(ds->devpoll, DP_POLL, &dvp);
-
- err = (nevents == -1) ? nxt_errno : 0;
-
- nxt_thread_time_update(thr);
-
- nxt_log_debug(thr->log, "ioctl(%d, DP_POLL): %d", ds->devpoll, nevents);
-
- if (nevents == -1) {
- level = (err == NXT_EINTR) ? NXT_LOG_INFO : NXT_LOG_ALERT;
- nxt_log_error(level, thr->log, "ioctl(%d, DP_POLL) failed %E",
- ds->devpoll, err);
- return;
- }
-
- for (i = 0; i < nevents; i++) {
-
- pfd = &ds->events[i];
- fd = pfd->fd;
- events = pfd->revents;
-
- ev = nxt_event_set_fd_hash_get(&ds->fd_hash, fd);
-
- if (nxt_slow_path(ev == NULL)) {
- nxt_log_alert(thr->log, "ioctl(%d, DP_POLL) returned invalid "
- "fd:%d ev:%04Xd rev:%04uXi",
- ds->devpoll, fd, pfd->events, events);
-
- nxt_devpoll_remove(thr, ds, fd);
- continue;
- }
-
- nxt_log_debug(ev->log, "devpoll: fd:%d ev:%04uXi rd:%d wr:%d",
- fd, events, ev->read, ev->write);
-
- if (nxt_slow_path(events & (POLLERR | POLLHUP | POLLNVAL)) != 0) {
- nxt_log_alert(ev->log,
- "ioctl(%d, DP_POLL) error fd:%d ev:%04Xd rev:%04uXi",
- ds->devpoll, fd, pfd->events, events);
-
- nxt_thread_work_queue_add(thr, &thr->work_queue.main,
- ev->error_handler, ev, ev->data, ev->log);
- continue;
- }
-
- if (events & POLLIN) {
- ev->read_ready = 1;
-
- if (ev->read != NXT_EVENT_BLOCKED) {
-
- if (ev->read == NXT_EVENT_ONESHOT) {
- nxt_devpoll_disable_read(event_set, ev);
- }
-
- nxt_thread_work_queue_add(thr, ev->read_work_queue,
- ev->read_handler,
- ev, ev->data, ev->log);
- }
- }
-
- if (events & POLLOUT) {
- ev->write_ready = 1;
-
- if (ev->write != NXT_EVENT_BLOCKED) {
-
- if (ev->write == NXT_EVENT_ONESHOT) {
- nxt_devpoll_disable_write(event_set, ev);
- }
-
- nxt_thread_work_queue_add(thr, ev->write_work_queue,
- ev->write_handler,
- ev, ev->data, ev->log);
- }
- }
- }
-}