Skip to content

Commit

Permalink
kqueue: use EVFILT_USER if available
Browse files Browse the repository at this point in the history
---------

Signed-off-by: Andy Pan <[email protected]>
  • Loading branch information
panjf2000 committed May 22, 2024
1 parent d2d92b7 commit 0d2e7cf
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 5 deletions.
27 changes: 23 additions & 4 deletions src/unix/async.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,14 +130,15 @@ void uv__async_close(uv_async_t* handle) {


static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
char buf[1024];
ssize_t r;
assert(w == &loop->async_io_watcher);

struct uv__queue queue;
struct uv__queue* q;
uv_async_t* h;
_Atomic int *pending;

assert(w == &loop->async_io_watcher);
#if !UV__KQUEUE_EVFILT_USER
char buf[1024];
ssize_t r;

for (;;) {
r = read(w->fd, buf, sizeof(buf));
Expand All @@ -156,6 +157,7 @@ static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {

abort();
}
#endif

uv__queue_move(&loop->async_handles, &queue);
while (!uv__queue_empty(&queue)) {
Expand All @@ -179,6 +181,14 @@ static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {


static void uv__async_send(uv_loop_t* loop) {
#if UV__KQUEUE_EVFILT_USER
struct kevent ev;

EV_SET(&ev, loop->async_io_watcher.fd, EVFILT_USER, 0, NOTE_TRIGGER, 0, 0);
int err = kevent(loop->backend_fd, &ev, 1, NULL, 0, NULL);
if (err == 0)
return;
#else
const void* buf;
ssize_t len;
int fd;
Expand Down Expand Up @@ -207,6 +217,7 @@ static void uv__async_send(uv_loop_t* loop) {
if (r == -1)
if (errno == EAGAIN || errno == EWOULDBLOCK)
return;
#endif

abort();
}
Expand All @@ -224,6 +235,14 @@ static int uv__async_start(uv_loop_t* loop) {
if (err < 0)
return UV__ERR(errno);

pipefd[0] = err;
pipefd[1] = -1;
#elif UV__KQUEUE_EVFILT_USER
/* This fd will not be actually used, it's only used as a placeholder. */
err = uv__open_cloexec("/dev/null", O_RDONLY);
if (err < 0)
return err;

pipefd[0] = err;
pipefd[1] = -1;
#else
Expand Down
18 changes: 17 additions & 1 deletion src/unix/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -927,6 +927,22 @@ void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
loop->watchers[w->fd] = w;
loop->nfds++;
}

#if UV__KQUEUE_EVFILT_USER
/* When using EVFILT_USER event to wake up the kqueue, this event must be
* registered beforehand. Otherwise, calling kevent() to issue an unregistered
* EVFILT_USER event will get an ENOENT.
* Since uv__async_send() may happen before uv__io_poll() with multi-threads,
* we can't defer this registration of EVFILT_USER event as we did for other
* events, but must perform it right away. */
if (w == &loop->async_io_watcher) {
struct kevent ev;
EV_SET(&ev, loop->async_io_watcher.fd, EVFILT_USER, EV_ADD | EV_CLEAR, 0, 0, 0);
if (kevent(loop->backend_fd, &ev, 1, NULL, 0, NULL))
abort();
w->events = w->pevents;
}
#endif
}


Expand Down Expand Up @@ -1677,7 +1693,7 @@ int uv_thread_setpriority(uv_thread_t tid, int priority) {
param.sched_priority = prio;
r = pthread_setschedparam(tid, policy, &param);
if (r != 0)
return UV__ERR(errno);
return UV__ERR(errno);
}

return 0;
Expand Down
13 changes: 13 additions & 0 deletions src/unix/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#if defined(__APPLE__) || defined(__DragonFly__) || \
defined(__FreeBSD__) || defined(__NetBSD__)
#include <sys/event.h>
#endif

#define uv__msan_unpoison(p, n) \
do { \
Expand Down Expand Up @@ -483,3 +487,12 @@ int uv__get_constrained_cpu(uv__cpu_constraint* constraint);
#endif

#endif /* UV_UNIX_INTERNAL_H_ */

/* EVFILT_USER is available since OS X 10.6, DragonFlyBSD 4.0 FreeBSD 8.1
* and NetBSD 10.0.
*/
#if defined(EVFILT_USER) && defined(NOTE_TRIGGER)
#define UV__KQUEUE_EVFILT_USER 1
#else
#define UV__KQUEUE_EVFILT_USER 0
#endif
4 changes: 4 additions & 0 deletions src/unix/kqueue.c
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,11 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {

revents = 0;

#if UV__KQUEUE_EVFILT_USER
if (ev->filter == EVFILT_READ || ev->filter == EVFILT_USER) {
#else
if (ev->filter == EVFILT_READ) {
#endif
if (w->pevents & POLLIN)
revents |= POLLIN;
else
Expand Down

0 comments on commit 0d2e7cf

Please sign in to comment.