diff options
Diffstat (limited to '')
-rw-r--r-- | src/nxt_pollset.c | 627 |
1 files changed, 0 insertions, 627 deletions
diff --git a/src/nxt_pollset.c b/src/nxt_pollset.c deleted file mode 100644 index 8d05e560..00000000 --- a/src/nxt_pollset.c +++ /dev/null @@ -1,627 +0,0 @@ - -/* - * Copyright (C) Igor Sysoev - * Copyright (C) NGINX, Inc. - */ - -#include <nxt_main.h> - - -/* - * pollset has been introduced in AIX 5L 5.3. - * - * pollset_create() returns a pollset_t descriptor which is not - * a file descriptor, so it cannot be added to another pollset. - * The first pollset_create() call returns 0. - */ - - -#define NXT_POLLSET_ADD 0 -#define NXT_POLLSET_UPDATE 1 -#define NXT_POLLSET_CHANGE 2 -#define NXT_POLLSET_DELETE 3 - - -static nxt_event_set_t *nxt_pollset_create(nxt_event_signals_t *signals, - nxt_uint_t mchanges, nxt_uint_t mevents); -static void nxt_pollset_free(nxt_event_set_t *event_set); -static void nxt_pollset_enable(nxt_event_set_t *event_set, nxt_event_fd_t *ev); -static void nxt_pollset_disable(nxt_event_set_t *event_set, nxt_event_fd_t *ev); -static void nxt_pollset_enable_read(nxt_event_set_t *event_set, - nxt_event_fd_t *ev); -static void nxt_pollset_enable_write(nxt_event_set_t *event_set, - nxt_event_fd_t *ev); -static void nxt_pollset_disable_read(nxt_event_set_t *event_set, - nxt_event_fd_t *ev); -static void nxt_pollset_disable_write(nxt_event_set_t *event_set, - nxt_event_fd_t *ev); -static void nxt_pollset_block_read(nxt_event_set_t *event_set, - nxt_event_fd_t *ev); -static void nxt_pollset_block_write(nxt_event_set_t *event_set, - nxt_event_fd_t *ev); -static void nxt_pollset_oneshot_read(nxt_event_set_t *event_set, - nxt_event_fd_t *ev); -static void nxt_pollset_oneshot_write(nxt_event_set_t *event_set, - nxt_event_fd_t *ev); -static void nxt_pollset_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_pollset_commit_changes(nxt_thread_t *thr, - nxt_pollset_event_set_t *ps); -static void nxt_pollset_change_error(nxt_thread_t *thr, - nxt_pollset_event_set_t *ps, nxt_event_fd_t *ev); -static void nxt_pollset_remove(nxt_thread_t *thr, nxt_pollset_event_set_t *ps, - nxt_fd_t fd); -static nxt_int_t nxt_pollset_write(nxt_thread_t *thr, int pollset, - struct poll_ctl *ctl, int n); -static void nxt_pollset_poll(nxt_thread_t *thr, nxt_event_set_t *event_set, - nxt_msec_t timeout); - - -const nxt_event_set_ops_t nxt_pollset_event_set = { - "pollset", - nxt_pollset_create, - nxt_pollset_free, - nxt_pollset_enable, - nxt_pollset_disable, - nxt_pollset_disable, - nxt_pollset_disable, - nxt_pollset_enable_read, - nxt_pollset_enable_write, - nxt_pollset_disable_read, - nxt_pollset_disable_write, - nxt_pollset_block_read, - nxt_pollset_block_write, - nxt_pollset_oneshot_read, - nxt_pollset_oneshot_write, - nxt_pollset_enable_read, - NULL, - NULL, - NULL, - NULL, - nxt_pollset_poll, - - &nxt_unix_event_conn_io, - - NXT_NO_FILE_EVENTS, - NXT_NO_SIGNAL_EVENTS, -}; - - -static nxt_event_set_t * -nxt_pollset_create(nxt_event_signals_t *signals, nxt_uint_t mchanges, - nxt_uint_t mevents) -{ - nxt_event_set_t *event_set; - nxt_pollset_event_set_t *ps; - - event_set = nxt_zalloc(sizeof(nxt_pollset_event_set_t)); - if (event_set == NULL) { - return NULL; - } - - ps = &event_set->pollset; - - ps->pollset = -1; - ps->mchanges = mchanges; - ps->mevents = mevents; - - ps->pollset_changes = nxt_malloc(sizeof(nxt_pollset_change_t) * mchanges); - if (ps->pollset_changes == NULL) { - goto fail; - } - - /* - * NXT_POLLSET_CHANGE requires two struct poll_ctl's - * for PS_DELETE and subsequent PS_ADD. - */ - ps->changes = nxt_malloc(2 * sizeof(struct poll_ctl) * mchanges); - if (ps->changes == NULL) { - goto fail; - } - - ps->events = nxt_malloc(sizeof(struct pollfd) * mevents); - if (ps->events == NULL) { - goto fail; - } - - ps->pollset = pollset_create(-1); - if (ps->pollset == -1) { - nxt_main_log_emerg("pollset_create() failed %E", nxt_errno); - goto fail; - } - - nxt_main_log_debug("pollset_create(): %d", ps->pollset); - - return event_set; - -fail: - - nxt_pollset_free(event_set); - - return NULL; -} - - -static void -nxt_pollset_free(nxt_event_set_t *event_set) -{ - nxt_pollset_event_set_t *ps; - - ps = &event_set->pollset; - - nxt_main_log_debug("pollset %d free", ps->pollset); - - if (ps->pollset != -1) { - if (pollset_destroy(ps->pollset) != 0) { - nxt_main_log_emerg("pollset_destroy(%d) failed %E", - ps->pollset, nxt_errno); - } - } - - nxt_free(ps->events); - nxt_free(ps->changes); - nxt_free(ps->pollset_changes); - nxt_event_set_fd_hash_destroy(&ps->fd_hash); - nxt_free(ps); -} - - -static void -nxt_pollset_enable(nxt_event_set_t *event_set, nxt_event_fd_t *ev) -{ - ev->read = NXT_EVENT_DEFAULT; - ev->write = NXT_EVENT_DEFAULT; - - nxt_pollset_change(event_set, ev, NXT_POLLSET_ADD, POLLIN | POLLOUT); -} - - -/* - * A closed descriptor must be deleted from a pollset, otherwise next - * pollset_poll() will return POLLNVAL on it. However, pollset_ctl() - * allows to delete the already closed file descriptor from the pollset - * using PS_DELETE, so the removal can be batched, pollset_ctl(2): - * - * After a file descriptor is added to a pollset, the file descriptor will - * not be removed until a pollset_ctl call with the cmd of PS_DELETE is - * executed. The file descriptor remains in the pollset even if the file - * descriptor is closed. A pollset_poll operation on a pollset containing - * a closed file descriptor returns a POLLNVAL event for that file - * descriptor. If the file descriptor is later allocated to a new object, - * the new object will be polled on future pollset_poll calls. - */ - -static void -nxt_pollset_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_pollset_change(event_set, ev, NXT_POLLSET_DELETE, 0); - } -} - - -static void -nxt_pollset_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_POLLSET_ADD; - - } else if (ev->write == NXT_EVENT_BLOCKED) { - ev->write = NXT_EVENT_INACTIVE; - op = NXT_POLLSET_CHANGE; - - } else { - op = NXT_POLLSET_UPDATE; - events = POLLIN | POLLOUT; - } - - nxt_pollset_change(event_set, ev, op, events); - } - - ev->read = NXT_EVENT_DEFAULT; -} - - -static void -nxt_pollset_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_POLLSET_ADD; - - } else if (ev->read == NXT_EVENT_BLOCKED) { - ev->read = NXT_EVENT_INACTIVE; - op = NXT_POLLSET_CHANGE; - - } else { - op = NXT_POLLSET_UPDATE; - events = POLLIN | POLLOUT; - } - - nxt_pollset_change(event_set, ev, op, events); - } - - ev->write = NXT_EVENT_DEFAULT; -} - - -static void -nxt_pollset_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_POLLSET_DELETE; - events = POLLREMOVE; - - } else { - op = NXT_POLLSET_CHANGE; - events = POLLOUT; - } - - nxt_pollset_change(event_set, ev, op, events); -} - - -static void -nxt_pollset_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_POLLSET_DELETE; - events = POLLREMOVE; - - } else { - op = NXT_POLLSET_CHANGE; - events = POLLIN; - } - - nxt_pollset_change(event_set, ev, op, events); -} - - -static void -nxt_pollset_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_pollset_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_pollset_oneshot_read(nxt_event_set_t *event_set, nxt_event_fd_t *ev) -{ - nxt_pollset_enable_read(event_set, ev); - - ev->read = NXT_EVENT_ONESHOT; -} - - -static void -nxt_pollset_oneshot_write(nxt_event_set_t *event_set, nxt_event_fd_t *ev) -{ - nxt_pollset_enable_write(event_set, ev); - - ev->write = NXT_EVENT_ONESHOT; -} - - -/* - * PS_ADD adds only a new file descriptor to a pollset. - * PS_DELETE removes a file descriptor from a pollset. - * - * PS_MOD can add a new file descriptor or modify events for a file - * descriptor which is already in a pollset. However, modified events - * are always ORed, so to delete an event for a file descriptor, - * the file descriptor must be removed using PS_DELETE and then - * added again without the event. - */ - -static void -nxt_pollset_change(nxt_event_set_t *event_set, nxt_event_fd_t *ev, - nxt_uint_t op, nxt_uint_t events) -{ - nxt_pollset_change_t *ch; - nxt_pollset_event_set_t *ps; - - ps = &event_set->pollset; - - nxt_log_debug(ev->log, "pollset %d change fd:%d op:%ui ev:%04Xi", - ps->pollset, ev->fd, op, events); - - if (ps->nchanges >= ps->mchanges) { - (void) nxt_pollset_commit_changes(nxt_thread(), ps); - } - - ch = &ps->pollset_changes[ps->nchanges++]; - ch->op = op; - ch->cmd = (op == NXT_POLLSET_DELETE) ? PS_DELETE : PS_MOD; - ch->fd = ev->fd; - ch->events = events; - ch->event = ev; -} - - -static nxt_int_t -nxt_pollset_commit_changes(nxt_thread_t *thr, nxt_pollset_event_set_t *ps) -{ - size_t n; - nxt_int_t ret, retval; - struct poll_ctl *ctl; - nxt_pollset_change_t *ch, *end; - - nxt_log_debug(thr->log, "pollset %d changes:%ui", - ps->pollset, ps->nchanges); - - retval = NXT_OK; - n = 0; - ch = ps->pollset_changes; - end = ch + ps->nchanges; - - do { - nxt_log_debug(thr->log, "pollset fd:%d op:%d ev:%04Xd", - ch->fd, ch->op, ch->events); - - if (ch->op == NXT_POLLSET_CHANGE) { - ctl = &ps->changes[n++]; - ctl->cmd = PS_DELETE; - ctl->events = 0; - ctl->fd = ch->fd; - } - - ctl = &ps->changes[n++]; - ctl->cmd = ch->cmd; - ctl->events = ch->events; - ctl->fd = ch->fd; - - ch++; - - } while (ch < end); - - ch = ps->pollset_changes; - end = ch + ps->nchanges; - - ret = nxt_pollset_write(thr, ps->pollset, ps->changes, n); - - if (nxt_slow_path(ret != NXT_OK)) { - do { - nxt_pollset_change_error(thr, ps, ch->event); - ch++; - } while (ch < end); - - ps->nchanges = 0; - - return NXT_ERROR; - } - - do { - if (ch->op == NXT_POLLSET_ADD) { - ret = nxt_event_set_fd_hash_add(&ps->fd_hash, ch->fd, ch->event); - - if (nxt_slow_path(ret != NXT_OK)) { - nxt_pollset_change_error(thr, ps, ch->event); - retval = NXT_ERROR; - } - - } else if (ch->op == NXT_POLLSET_DELETE) { - nxt_event_set_fd_hash_delete(&ps->fd_hash, ch->fd, 0); - } - - /* Nothing to do for NXT_POLLSET_UPDATE and NXT_POLLSET_CHANGE. */ - - ch++; - - } while (ch < end); - - ps->nchanges = 0; - - return retval; -} - - -static void -nxt_pollset_change_error(nxt_thread_t *thr, nxt_pollset_event_set_t *ps, - 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(&ps->fd_hash, ev->fd, 1); - - nxt_pollset_remove(thr, ps, ev->fd); -} - - -static void -nxt_pollset_remove(nxt_thread_t *thr, nxt_pollset_event_set_t *ps, nxt_fd_t fd) -{ - int n; - struct pollfd pfd; - struct poll_ctl ctl; - - pfd.fd = fd; - pfd.events = 0; - pfd.revents = 0; - - n = pollset_query(ps->pollset, &pfd); - - nxt_thread_log_debug("pollset_query(%d, %d): %d", ps->pollset, fd, n); - - if (n == 0) { - /* The file descriptor is not in the pollset. */ - return; - } - - if (n == -1) { - nxt_thread_log_alert("pollset_query(%d, %d) failed %E", - ps->pollset, fd, nxt_errno); - /* Fall through. */ - } - - /* n == 1: The file descriptor is in the pollset. */ - - nxt_thread_log_debug("pollset %d remove fd:%d", ps->pollset, fd); - - ctl.cmd = PS_DELETE; - ctl.events = 0; - ctl.fd = fd; - - nxt_pollset_write(thr, ps->pollset, &ctl, 1); -} - - -static nxt_int_t -nxt_pollset_write(nxt_thread_t *thr, int pollset, struct poll_ctl *ctl, int n) -{ - nxt_thread_log_debug("pollset_ctl(%d) changes:%d", pollset, n); - - nxt_set_errno(0); - - n = pollset_ctl(pollset, ctl, n); - - if (nxt_fast_path(n == 0)) { - return NXT_OK; - } - - nxt_log_alert(thr->log, "pollset_ctl(%d) failed: %d %E", - pollset, n, nxt_errno); - - return NXT_ERROR; -} - - -static void -nxt_pollset_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 pollfd *pfd; - nxt_event_fd_t *ev; - nxt_pollset_event_set_t *ps; - - ps = &event_set->pollset; - - if (ps->nchanges != 0) { - if (nxt_pollset_commit_changes(thr, ps) != NXT_OK) { - /* Error handlers have been enqueued on failure. */ - timeout = 0; - } - } - - nxt_log_debug(thr->log, "pollset_poll(%d) timeout:%M", - ps->pollset, timeout); - - nevents = pollset_poll(ps->pollset, ps->events, ps->mevents, timeout); - - err = (nevents == -1) ? nxt_errno : 0; - - nxt_thread_time_update(thr); - - nxt_log_debug(thr->log, "pollset_poll(%d): %d", ps->pollset, nevents); - - if (nevents == -1) { - level = (err == NXT_EINTR) ? NXT_LOG_INFO : NXT_LOG_ALERT; - nxt_log_error(level, thr->log, "pollset_poll(%d) failed %E", - ps->pollset, err); - return; - } - - for (i = 0; i < nevents; i++) { - - pfd = &ps->events[i]; - fd = pfd->fd; - events = pfd->revents; - - ev = nxt_event_set_fd_hash_get(&ps->fd_hash, fd); - - if (nxt_slow_path(ev == NULL)) { - nxt_log_alert(thr->log, "pollset_poll(%d) returned invalid " - "fd:%d ev:%04Xd rev:%04uXi", - ps->pollset, fd, pfd->events, events); - - nxt_pollset_remove(thr, ps, fd); - continue; - } - - nxt_log_debug(ev->log, "pollset: fd:%d ev:%04uXi", fd, events); - - if (nxt_slow_path(events & (POLLERR | POLLHUP | POLLNVAL)) != 0) { - nxt_log_alert(ev->log, - "pollset_poll(%d) error fd:%d ev:%04Xd rev:%04uXi", - ps->pollset, 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_pollset_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_pollset_disable_write(event_set, ev); - } - - nxt_thread_work_queue_add(thr, ev->write_work_queue, - ev->write_handler, - ev, ev->data, ev->log); - } - } - } -} |