static int poll_add(struct event_base *base, int fd, short old, short events, void *_idx) { struct pollop *pop = base->evbase; struct pollfd *pfd = NULL; struct pollidx *idx = _idx; int i; EVUTIL_ASSERT((events & EV_SIGNAL) == 0); if (!(events & (EV_READ|EV_WRITE))) return (0); poll_check_ok(pop); if (pop->nfds + 1 >= pop->event_count) { struct pollfd *tmp_event_set; int tmp_event_count; if (pop->event_count < 32) tmp_event_count = 32; else tmp_event_count = pop->event_count * 2; /* We need more file descriptors */ tmp_event_set = mm_realloc(pop->event_set, tmp_event_count * sizeof(struct pollfd)); if (tmp_event_set == NULL) { event_warn("realloc"); return (-1); } pop->event_set = tmp_event_set; pop->event_count = tmp_event_count; pop->realloc_copy = 1; } i = idx->idxplus1 - 1; if (i >= 0) { pfd = &pop->event_set[i]; } else { i = pop->nfds++; pfd = &pop->event_set[i]; pfd->events = 0; pfd->fd = fd; idx->idxplus1 = i + 1; } pfd->revents = 0; if (events & EV_WRITE) pfd->events |= POLLOUT; if (events & EV_READ) pfd->events |= POLLIN; poll_check_ok(pop); return (0); }
static int poll_del(void *arg, struct event *ev) { struct pollop *pop = arg; struct pollfd *pfd = NULL; int i; if (ev->ev_events & EV_SIGNAL) return (evsignal_del(ev)); if (!(ev->ev_events & (EV_READ|EV_WRITE))) return (0); poll_check_ok(pop); i = pop->idxplus1_by_fd[ev->ev_fd] - 1; if (i < 0) return (-1); /* Do we still want to read or write? */ pfd = &pop->event_set[i]; if (ev->ev_events & EV_READ) { pfd->events &= ~POLLIN; pop->event_r_back[i] = NULL; } if (ev->ev_events & EV_WRITE) { pfd->events &= ~POLLOUT; pop->event_w_back[i] = NULL; } poll_check_ok(pop); if (pfd->events) /* Another event cares about that fd. */ return (0); /* Okay, so we aren't interested in that fd anymore. */ pop->idxplus1_by_fd[ev->ev_fd] = 0; --pop->nfds; if (i != pop->nfds) { /* * Shift the last pollfd down into the now-unoccupied * position. */ memcpy(&pop->event_set[i], &pop->event_set[pop->nfds], sizeof(struct pollfd)); pop->event_r_back[i] = pop->event_r_back[pop->nfds]; pop->event_w_back[i] = pop->event_w_back[pop->nfds]; pop->idxplus1_by_fd[pop->event_set[i].fd] = i + 1; } poll_check_ok(pop); return (0); }
static int poll_del(struct event_base *base, int fd, short old, short events, void *_idx) { struct pollop *pop = base->evbase; struct pollfd *pfd = NULL; struct pollidx *idx = _idx; int i; EVUTIL_ASSERT((events & EV_SIGNAL) == 0); if (!(events & (EV_READ|EV_WRITE))) return (0); poll_check_ok(pop); i = idx->idxplus1 - 1; if (i < 0) return (-1); /* Do we still want to read or write? */ pfd = &pop->event_set[i]; if (events & EV_READ) pfd->events &= ~POLLIN; if (events & EV_WRITE) pfd->events &= ~POLLOUT; poll_check_ok(pop); if (pfd->events) /* Another event cares about that fd. */ return (0); /* Okay, so we aren't interested in that fd anymore. */ idx->idxplus1 = 0; --pop->nfds; if (i != pop->nfds) { /* * Shift the last pollfd down into the now-unoccupied * position. */ memcpy(&pop->event_set[i], &pop->event_set[pop->nfds], sizeof(struct pollfd)); idx = evmap_io_get_fdinfo(&base->io, pop->event_set[i].fd); EVUTIL_ASSERT(idx); EVUTIL_ASSERT(idx->idxplus1 == pop->nfds + 1); idx->idxplus1 = i + 1; } poll_check_ok(pop); return (0); }
static int poll_add(void *arg, struct event *ev) { struct pollop *pop = arg; struct pollfd *pfd = NULL; int i; if (ev->ev_events & EV_SIGNAL) return (evsignal_add(ev)); if (!(ev->ev_events & (EV_READ|EV_WRITE))) return (0); poll_check_ok(pop); if (pop->nfds + 1 >= pop->event_count) { struct pollfd *tmp_event_set; struct event **tmp_event_r_back; struct event **tmp_event_w_back; int tmp_event_count; if (pop->event_count < 32) tmp_event_count = 32; else tmp_event_count = pop->event_count * 2; /* We need more file descriptors */ tmp_event_set = realloc(pop->event_set, tmp_event_count * sizeof(struct pollfd)); if (tmp_event_set == NULL) { event_warn("realloc"); return (-1); } pop->event_set = tmp_event_set; tmp_event_r_back = realloc(pop->event_r_back, tmp_event_count * sizeof(struct event *)); if (tmp_event_r_back == NULL) { /* event_set overallocated; that's okay. */ event_warn("realloc"); return (-1); } pop->event_r_back = tmp_event_r_back; tmp_event_w_back = realloc(pop->event_w_back, tmp_event_count * sizeof(struct event *)); if (tmp_event_w_back == NULL) { /* event_set and event_r_back overallocated; that's * okay. */ event_warn("realloc"); return (-1); } pop->event_w_back = tmp_event_w_back; pop->event_count = tmp_event_count; } if (ev->ev_fd >= pop->fd_count) { int *tmp_idxplus1_by_fd; int new_count; if (pop->fd_count < 32) new_count = 32; else new_count = pop->fd_count * 2; while (new_count <= ev->ev_fd) new_count *= 2; tmp_idxplus1_by_fd = realloc(pop->idxplus1_by_fd, new_count * sizeof(int)); if (tmp_idxplus1_by_fd == NULL) { event_warn("realloc"); return (-1); } pop->idxplus1_by_fd = tmp_idxplus1_by_fd; memset(pop->idxplus1_by_fd + pop->fd_count, 0, sizeof(int)*(new_count - pop->fd_count)); pop->fd_count = new_count; } i = pop->idxplus1_by_fd[ev->ev_fd] - 1; if (i >= 0) { pfd = &pop->event_set[i]; } else { i = pop->nfds++; pfd = &pop->event_set[i]; pfd->events = 0; pfd->fd = ev->ev_fd; pop->event_w_back[i] = pop->event_r_back[i] = NULL; pop->idxplus1_by_fd[ev->ev_fd] = i + 1; } pfd->revents = 0; if (ev->ev_events & EV_WRITE) { pfd->events |= POLLOUT; pop->event_w_back[i] = ev; } if (ev->ev_events & EV_READ) { pfd->events |= POLLIN; pop->event_r_back[i] = ev; } poll_check_ok(pop); return (0); }
static int poll_dispatch(struct event_base *base, void *arg, struct timeval *tv) { int res, i, j, msec = -1, nfds; struct pollop *pop = arg; poll_check_ok(pop); if (tv != NULL) msec = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000; nfds = pop->nfds; res = poll(pop->event_set, nfds, msec); if (res == -1) { if (errno != EINTR) { event_warn("poll"); return (-1); } evsignal_process(base); return (0); } else if (base->sig.evsignal_caught) { evsignal_process(base); } event_debug(("%s: poll reports %d", __func__, res)); if (res == 0 || nfds == 0) return (0); i = random() % nfds; for (j = 0; j < nfds; j++) { struct event *r_ev = NULL, *w_ev = NULL; int what; if (++i == nfds) i = 0; what = pop->event_set[i].revents; if (!what) continue; res = 0; /* If the file gets closed notify */ if (what & (POLLHUP|POLLERR)) what |= POLLIN|POLLOUT; if (what & POLLIN) { res |= EV_READ; r_ev = pop->event_r_back[i]; } if (what & POLLOUT) { res |= EV_WRITE; w_ev = pop->event_w_back[i]; } if (res == 0) continue; if (r_ev && (res & r_ev->ev_events)) { event_active(r_ev, res & r_ev->ev_events, 1); } if (w_ev && w_ev != r_ev && (res & w_ev->ev_events)) { event_active(w_ev, res & w_ev->ev_events, 1); } } return (0); }
static int poll_dispatch(struct event_base *base, struct timeval *tv) { int res, i, j, nfds; long msec = -1; struct pollop *pop = base->evbase; struct pollfd *event_set; poll_check_ok(pop); nfds = pop->nfds; #ifndef _EVENT_DISABLE_THREAD_SUPPORT if (base->th_base_lock) { /* If we're using this backend in a multithreaded setting, * then we need to work on a copy of event_set, so that we can * let other threads modify the main event_set while we're * polling. If we're not multithreaded, then we'll skip the * copy step here to save memory and time. */ if (pop->realloc_copy) { struct pollfd *tmp = mm_realloc(pop->event_set_copy, pop->event_count * sizeof(struct pollfd)); if (tmp == NULL) { event_warn("realloc"); return -1; } pop->event_set_copy = tmp; pop->realloc_copy = 0; } memcpy(pop->event_set_copy, pop->event_set, sizeof(struct pollfd)*nfds); event_set = pop->event_set_copy; } else { event_set = pop->event_set; } #else event_set = pop->event_set; #endif if (tv != NULL) { msec = evutil_tv_to_msec(tv); if (msec < 0 || msec > INT_MAX) msec = INT_MAX; } EVBASE_RELEASE_LOCK(base, th_base_lock); res = poll(event_set, nfds, msec); EVBASE_ACQUIRE_LOCK(base, th_base_lock); if (res == -1) { if (errno != EINTR) { event_warn("poll"); return (-1); } return (0); } event_debug(("%s: poll reports %d", __func__, res)); if (res == 0 || nfds == 0) return (0); i = random() % nfds; for (j = 0; j < nfds; j++) { int what; if (++i == nfds) i = 0; what = event_set[i].revents; if (!what) continue; res = 0; /* If the file gets closed notify */ if (what & (POLLHUP|POLLERR)) what |= POLLIN|POLLOUT; if (what & POLLIN) res |= EV_READ; if (what & POLLOUT) res |= EV_WRITE; if (res == 0) continue; evmap_io_active(base, event_set[i].fd, res); } return (0); }
int poll_dispatch(struct event_base *base, void *arg, struct timeval *tv) { int res, i, sec, nfds; struct pollop *pop = arg; poll_check_ok(pop); sec = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000; nfds = pop->nfds; res = poll(pop->event_set, nfds, sec); if (res == -1) { if (errno != EINTR) { event_warn("poll"); return (-1); } evsignal_process(); return (0); } else if (evsignal_caught) evsignal_process(); event_debug(("%s: poll reports %d", __func__, res)); if (res == 0) return (0); for (i = 0; i < nfds; i++) { int what = pop->event_set[i].revents; struct event *r_ev = NULL, *w_ev = NULL; if (!what) continue; res = 0; /* If the file gets closed notify */ if (what & (POLLHUP|POLLERR)) what |= POLLIN|POLLOUT; if (what & POLLIN) { res |= EV_READ; r_ev = pop->event_r_back[i]; } if (what & POLLOUT) { res |= EV_WRITE; w_ev = pop->event_w_back[i]; } if (res == 0) continue; if (r_ev && (res & r_ev->ev_events)) { if (!(r_ev->ev_events & EV_PERSIST)) event_del(r_ev); event_active(r_ev, res & r_ev->ev_events, 1); } if (w_ev && w_ev != r_ev && (res & w_ev->ev_events)) { if (!(w_ev->ev_events & EV_PERSIST)) event_del(w_ev); event_active(w_ev, res & w_ev->ev_events, 1); } } return (0); }