26 #if _POSIX_C_SOURCE >= 200112L
43 #ifndef LELY_HAVE_PPOLL
46 #if defined(__linux__) || (__FreeBSD__ >= 11)
47 #define LELY_HAVE_PPOLL 1
54 #include <sys/select.h>
58 #ifndef LELY_IO_PPOLL_NFDS
59 #define LELY_IO_PPOLL_NFDS MAX((LELY_VLA_SIZE_MAX / sizeof(struct pollfd)), 1)
72 static const struct io_svc_vtbl io_poll_svc_vtbl = {
78 static void *io_poll_poll_self(
const ev_poll_t *poll);
79 static int io_poll_poll_wait(
ev_poll_t *poll,
int timeout);
80 static int io_poll_poll_kill(
ev_poll_t *poll,
void *thr);
95 struct sigaction oact;
109 static void io_poll_process(
112 static int io_fd_cmp(
const void *p1,
const void *p2);
117 static void sig_ign(
int signo);
126 io_poll_free(
void *ptr)
145 poll->poll_vptr = &io_poll_poll_vtbl;
149 struct sigaction act;
150 act.sa_handler = &sig_ign;
151 sigemptyset(&act.sa_mask);
153 if (sigaction(poll->signo, &act, &poll->oact) == -1) {
155 goto error_sigaction;
161 sigaddset(&set, poll->signo);
163 if (sigprocmask(SIG_BLOCK, &set, &poll->oset) == -1) {
166 if ((errsv = pthread_sigmask(SIG_BLOCK, &set, &poll->oset))) {
172 if ((errsv = pthread_mutex_init(&poll->
mtx, NULL)))
191 sigprocmask(SIG_SETMASK, &poll->oset, NULL);
193 pthread_sigmask(SIG_SETMASK, &poll->oset, NULL);
196 sigaction(poll->signo, &poll->oact, NULL);
214 pthread_mutex_destroy(&poll->
mtx);
220 sigaddset(&set, poll->signo);
222 while (sigtimedwait(&set, &(siginfo_t){ 0 }, &(
struct timespec){ 0, 0 })
228 sigprocmask(SIG_SETMASK, &poll->oset, NULL);
230 pthread_sigmask(SIG_SETMASK, &poll->oset, NULL);
232 sigaction(poll->signo, &poll->oact, NULL);
246 io_poll_t *tmp = io_poll_init(poll, ctx, signo);
280 return &poll->poll_vptr;
298 events &= IO_EVENT_MASK;
303 pthread_mutex_lock(&poll->
mtx);
308 if (node != &watch->_node) {
328 if (events != watch->_events) {
329 watch->_events = events;
337 pthread_kill(*thr->thread, poll->signo);
347 pthread_mutex_unlock(&poll->
mtx);
364 thread = pthread_self();
365 thr.thread = &thread;
372 io_poll_poll_wait(
ev_poll_t *poll_,
int timeout_)
374 io_poll_t *poll = io_poll_from_poll(poll_);
375 void *thr_ = io_poll_poll_self(poll_);
378 struct timespec tv = { 0, 0 };
380 tv.tv_sec = timeout_ / 1000;
381 tv.tv_nsec = (timeout_ % 1000) * 1000000l;
383 struct timespec *timeout = timeout_ >= 0 ? &tv : NULL;
392 struct pollfd fds_[LELY_IO_PPOLL_NFDS];
393 struct pollfd *fds = fds_;
395 fd_set rfds, wfds, efds;
399 pthread_mutex_lock(&poll->
mtx);
411 tv = (
struct timespec){ 0, 0 };
420 if (nfds > LELY_IO_PPOLL_NFDS) {
421 fds = malloc(nfds *
sizeof(*fds));
432 io_poll_watch_from_node(node);
437 events |= POLLRDBAND | POLLPRI;
440 fds[i++] = (
struct pollfd){ .fd = watch->_fd,
455 io_poll_watch_from_node(node);
457 FD_SET(watch->_fd, &rfds);
458 nrfds =
MAX(nrfds, watch->_fd + 1);
461 FD_SET(watch->_fd, &wfds);
462 nwfds =
MAX(nwfds, watch->_fd + 1);
464 FD_SET(watch->_fd, &efds);
465 nefds =
MAX(nefds, watch->_fd + 1);
470 pthread_mutex_unlock(&poll->
mtx);
474 int result = ppoll(fds, nfds, timeout, &set);
476 int result = pselect(nefds, nrfds ? &rfds : NULL,
477 nwfds ? &wfds : NULL, nefds ? &efds : NULL,
481 pthread_mutex_lock(&poll->
mtx);
484 if (errno == EINTR) {
492 sigaddset(&set, poll->signo);
503 for (i = 0; i < nfds; i++) {
504 if (!fds[i].revents || (fds[i].revents & POLLNVAL))
511 io_poll_watch_from_node(node);
513 if (fds[i].revents & POLLIN)
515 if (fds[i].revents & (POLLRDBAND | POLLPRI))
517 if (fds[i].revents & POLLOUT)
519 if (fds[i].revents & POLLERR)
521 if (fds[i].revents & POLLHUP)
523 io_poll_process(poll, revents, watch);
529 io_poll_watch_from_node(node);
533 if (FD_ISSET(watch->_fd, &rfds))
535 if (FD_ISSET(watch->_fd, &wfds))
537 if (FD_ISSET(watch->_fd, &efds)) {
544 io_poll_process(poll, revents, watch);
550 stopped = thr->stopped = 1;
557 pthread_mutex_unlock(&poll->
mtx);
570 io_poll_poll_kill(
ev_poll_t *poll_,
void *thr_)
573 io_poll_t *poll = io_poll_from_poll(poll_);
578 if (thr_ == io_poll_poll_self(poll_))
582 pthread_mutex_lock(&poll->
mtx);
584 int stopped = thr->stopped;
588 pthread_mutex_unlock(&poll->
mtx);
590 int errsv = pthread_kill(*thr->thread, poll->signo);
601 io_poll_from_svc(
const struct io_svc *svc)
626 pthread_mutex_unlock(&poll->
mtx);
628 watch->
func(watch, revents);
630 pthread_mutex_lock(&poll->
mtx);
636 io_fd_cmp(
const void *p1,
const void *p2)
639 int fd1 = *(
const int *)p1;
641 int fd2 = *(
const int *)p2;
643 return (fd2 < fd1) - (fd1 < fd2);
647 io_poll_watch_from_node(
struct rbnode *node)
660 #endif // _POSIX_C_SOURCE >= 200112L