26 #if !LELY_NO_STDIO && defined(__linux__)
42 #include <sys/epoll.h>
45 #define EPOLL_EVENT_INIT(events, fd) \
47 (((events) & IO_EVENT_IN) ? (EPOLLIN | EPOLLRDHUP) : 0) \
48 | (((events) & IO_EVENT_PRI) ? EPOLLPRI : 0) \
49 | (((events) & IO_EVENT_OUT) ? EPOLLOUT : 0) \
55 #ifndef LELY_IO_EPOLL_MAXEVENTS
56 #define LELY_IO_EPOLL_MAXEVENTS \
57 MAX((LELY_VLA_SIZE_MAX / sizeof(struct epoll_event)), 1)
70 static const struct io_svc_vtbl io_poll_svc_vtbl = {
71 &io_poll_svc_notify_fork,
76 static void *io_poll_poll_self(
const ev_poll_t *poll);
77 static int io_poll_poll_wait(
ev_poll_t *poll,
int timeout);
78 static int io_poll_poll_kill(
ev_poll_t *poll,
void *thr);
93 struct sigaction oact;
106 static int io_poll_open(
io_poll_t *poll);
107 static int io_poll_close(
io_poll_t *poll);
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))) {
173 if ((errsv = pthread_mutex_init(&poll->
mtx, NULL)))
180 if (io_poll_open(poll) == -1) {
192 pthread_mutex_destroy(&poll->
mtx);
196 sigprocmask(SIG_SETMASK, &poll->oset, NULL);
198 pthread_sigmask(SIG_SETMASK, &poll->oset, NULL);
201 sigaction(poll->signo, &poll->oact, NULL);
217 pthread_mutex_destroy(&poll->
mtx);
223 sigaddset(&set, poll->signo);
225 while (sigtimedwait(&set, &(siginfo_t){ 0 }, &(
struct timespec){ 0, 0 })
231 sigprocmask(SIG_SETMASK, &poll->oset, NULL);
233 pthread_sigmask(SIG_SETMASK, &poll->oset, NULL);
235 sigaction(poll->signo, &poll->oact, NULL);
249 io_poll_t *tmp = io_poll_init(poll, ctx, signo);
283 return &poll->poll_vptr;
291 int epfd = poll->
epfd;
293 if (fd == -1 || fd == epfd) {
302 events &= IO_EVENT_MASK;
307 pthread_mutex_lock(&poll->
mtx);
311 if (node && node != &watch->_node) {
317 struct epoll_event event = EPOLL_EVENT_INIT(events, fd);
318 if (node && events != watch->_events) {
319 if (epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &event) == -1) {
321 epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL);
329 if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event) == -1) {
340 watch->_events = events;
342 epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL);
353 pthread_mutex_unlock(&poll->
mtx);
370 if (io_poll_close(poll) == -1) {
375 if (io_poll_open(poll) == -1 && !result) {
380 int epfd = poll->
epfd;
384 int events = watch->_events;
386 struct epoll_event event = EPOLL_EVENT_INIT(events, fd);
388 if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event) == -1) {
415 thread = pthread_self();
416 thr.thread = &thread;
423 io_poll_poll_wait(
ev_poll_t *poll_,
int timeout)
425 io_poll_t *poll = io_poll_from_poll(poll_);
426 void *thr_ = io_poll_poll_self(poll_);
435 struct epoll_event events[LELY_IO_EPOLL_MAXEVENTS];
438 pthread_mutex_lock(&poll->
mtx);
452 pthread_mutex_unlock(&poll->
mtx);
455 int nevents = epoll_pwait(poll->
epfd, events,
456 LELY_IO_EPOLL_MAXEVENTS, timeout, &set);
457 if (nevents == -1 && errno == EINTR) {
464 sigaddset(&set, poll->signo);
466 pthread_mutex_lock(&poll->
mtx);
477 pthread_mutex_lock(&poll->
mtx);
482 for (
int i = 0; i < nevents; i++) {
484 if (events[i].events & (EPOLLIN | EPOLLRDHUP))
486 if (events[i].events & EPOLLPRI)
488 if (events[i].events & EPOLLOUT)
490 if (events[i].events & EPOLLERR)
492 if (events[i].events & EPOLLHUP)
494 int fd = events[i].data.fd;
496 pthread_mutex_lock(&poll->
mtx);
501 io_poll_watch_from_node(node);
502 io_poll_process(poll, revents, watch);
506 pthread_mutex_unlock(&poll->
mtx);
511 pthread_mutex_lock(&poll->
mtx);
514 stopped = nevents != LELY_IO_EPOLL_MAXEVENTS;
518 pthread_mutex_unlock(&poll->
mtx);
526 io_poll_poll_kill(
ev_poll_t *poll_,
void *thr_)
529 io_poll_t *poll = io_poll_from_poll(poll_);
534 if (thr_ == io_poll_poll_self(poll_))
538 pthread_mutex_lock(&poll->
mtx);
540 int stopped = thr->stopped;
544 pthread_mutex_unlock(&poll->
mtx);
546 int errsv = pthread_kill(*thr->thread, poll->signo);
557 io_poll_from_svc(
const struct io_svc *svc)
575 if (io_poll_close(poll) == -1)
578 return (poll->
epfd = epoll_create1(EPOLL_CLOEXEC)) == -1 ? -1 : 0;
586 int epfd = poll->
epfd;
598 assert(poll->nwatch);
600 assert(watch->_events);
607 pthread_mutex_unlock(&poll->
mtx);
609 watch->
func(watch, revents);
611 pthread_mutex_lock(&poll->
mtx);
617 io_fd_cmp(
const void *p1,
const void *p2)
620 int fd1 = *(
const int *)p1;
622 int fd2 = *(
const int *)p2;
624 return (fd2 < fd1) - (fd1 < fd2);
628 io_poll_watch_from_node(
struct rbnode *node)
641 #endif // !LELY_NO_STDIO && __linux__