2016-03-19 15:14:35 +00:00
|
|
|
#include "first.h"
|
|
|
|
|
2017-11-01 04:16:38 +00:00
|
|
|
#include "fdevent_impl.h"
|
2009-10-11 14:31:42 +00:00
|
|
|
#include "fdevent.h"
|
|
|
|
#include "buffer.h"
|
2005-02-20 14:27:00 +00:00
|
|
|
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <errno.h>
|
|
|
|
|
2017-11-01 04:16:38 +00:00
|
|
|
#ifdef FDEVENT_USE_POLL
|
2011-12-25 15:35:01 +00:00
|
|
|
|
|
|
|
# ifdef HAVE_POLL_H
|
|
|
|
# include <poll.h>
|
|
|
|
# else
|
|
|
|
# include <sys/poll.h>
|
|
|
|
# endif
|
|
|
|
|
2019-02-23 06:35:58 +00:00
|
|
|
__attribute_cold__
|
2005-02-20 14:27:00 +00:00
|
|
|
static void fdevent_poll_free(fdevents *ev) {
|
|
|
|
free(ev->pollfds);
|
|
|
|
if (ev->unused.ptr) free(ev->unused.ptr);
|
|
|
|
}
|
|
|
|
|
2019-02-23 06:35:58 +00:00
|
|
|
static int fdevent_poll_event_del(fdevents *ev, fdnode *fdn) {
|
|
|
|
int fd = fdn->fd;
|
|
|
|
int k = fdn->fde_ndx;
|
2019-12-10 03:13:44 +00:00
|
|
|
if ((uint32_t)k >= ev->used || ev->pollfds[k].fd != fd) return (errno = EINVAL, -1);
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
ev->pollfds[k].fd = -1;
|
|
|
|
/* ev->pollfds[k].events = 0; */
|
|
|
|
/* ev->pollfds[k].revents = 0; */
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2019-02-13 03:36:04 +00:00
|
|
|
if (ev->unused.size == ev->unused.used) {
|
2005-02-20 14:27:00 +00:00
|
|
|
ev->unused.size += 16;
|
|
|
|
ev->unused.ptr = realloc(ev->unused.ptr, sizeof(*(ev->unused.ptr)) * ev->unused.size);
|
2016-01-30 13:59:07 +00:00
|
|
|
force_assert(NULL != ev->unused.ptr);
|
2005-02-20 14:27:00 +00:00
|
|
|
}
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
ev->unused.ptr[ev->unused.used++] = k;
|
2010-08-06 21:57:15 +00:00
|
|
|
|
2019-02-23 06:35:58 +00:00
|
|
|
return 0;
|
2005-02-20 14:27:00 +00:00
|
|
|
}
|
|
|
|
|
2019-02-23 06:35:58 +00:00
|
|
|
static int fdevent_poll_event_set(fdevents *ev, fdnode *fdn, int events) {
|
|
|
|
int fd = fdn->fd;
|
|
|
|
int k = fdn->fde_ndx;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2019-03-16 21:38:40 +00:00
|
|
|
#ifndef POLLRDHUP
|
|
|
|
events &= ~FDEVENT_RDHUP;
|
|
|
|
#endif
|
|
|
|
|
2019-02-23 06:35:58 +00:00
|
|
|
if (k >= 0) {
|
2019-12-10 03:13:44 +00:00
|
|
|
if ((uint32_t)k >= ev->used || ev->pollfds[k].fd != fd) return (errno = EINVAL, -1);
|
2019-02-23 06:35:58 +00:00
|
|
|
ev->pollfds[k].events = events;
|
|
|
|
return 0;
|
2005-02-20 14:27:00 +00:00
|
|
|
}
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
if (ev->unused.used > 0) {
|
2019-02-17 23:35:05 +00:00
|
|
|
k = ev->unused.ptr[--ev->unused.used];
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
} else {
|
2019-02-13 03:36:04 +00:00
|
|
|
if (ev->size == ev->used) {
|
2005-02-20 14:27:00 +00:00
|
|
|
ev->size += 16;
|
|
|
|
ev->pollfds = realloc(ev->pollfds, sizeof(*ev->pollfds) * ev->size);
|
2016-01-30 13:59:07 +00:00
|
|
|
force_assert(NULL != ev->pollfds);
|
2005-02-20 14:27:00 +00:00
|
|
|
}
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2019-02-17 23:35:05 +00:00
|
|
|
k = ev->used++;
|
2005-02-20 14:27:00 +00:00
|
|
|
}
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2019-02-23 06:35:58 +00:00
|
|
|
fdn->fde_ndx = k;
|
2019-02-17 23:35:05 +00:00
|
|
|
ev->pollfds[k].fd = fd;
|
|
|
|
ev->pollfds[k].events = events;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2019-02-23 06:35:58 +00:00
|
|
|
return 0;
|
2005-02-20 14:27:00 +00:00
|
|
|
}
|
|
|
|
|
2019-02-17 23:35:05 +00:00
|
|
|
static int fdevent_poll_next_ndx(const fdevents *ev, int ndx) {
|
2019-12-10 03:13:44 +00:00
|
|
|
for (uint32_t i = (uint32_t)(ndx+1); i < ev->used; ++i) {
|
2010-08-06 21:57:15 +00:00
|
|
|
if (ev->pollfds[i].revents) return i;
|
2005-02-20 14:27:00 +00:00
|
|
|
}
|
2010-08-06 21:57:15 +00:00
|
|
|
return -1;
|
2005-02-20 14:27:00 +00:00
|
|
|
}
|
|
|
|
|
2019-02-14 02:34:59 +00:00
|
|
|
static int fdevent_poll_poll(fdevents *ev, int timeout_ms) {
|
2019-02-17 23:35:05 +00:00
|
|
|
const int n = poll(ev->pollfds, ev->used, timeout_ms);
|
|
|
|
for (int ndx=-1,i=0; i<n && -1!=(ndx=fdevent_poll_next_ndx(ev,ndx)); ++i){
|
|
|
|
fdnode *fdn = ev->fdarray[ev->pollfds[ndx].fd];
|
2019-02-23 06:35:58 +00:00
|
|
|
int revents = ev->pollfds[ndx].revents;
|
2019-02-14 02:34:59 +00:00
|
|
|
if (0 == ((uintptr_t)fdn & 0x3)) {
|
2019-12-21 03:03:51 +00:00
|
|
|
(*fdn->handler)(fdn->ctx, revents);
|
2019-02-14 02:34:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
2019-02-23 06:35:58 +00:00
|
|
|
__attribute_cold__
|
2005-02-20 14:27:00 +00:00
|
|
|
int fdevent_poll_init(fdevents *ev) {
|
2019-02-17 23:35:05 +00:00
|
|
|
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);
|
2019-02-23 06:35:58 +00:00
|
|
|
#ifdef POLLRDHUP
|
2019-02-17 23:35:05 +00:00
|
|
|
force_assert(POLLRDHUP == FDEVENT_RDHUP);
|
|
|
|
#endif
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2019-02-23 06:35:58 +00:00
|
|
|
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;
|
2005-02-20 14:27:00 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|