diff options
Diffstat (limited to 'deps/uv/src/unix/linux-core.c')
-rw-r--r-- | deps/uv/src/unix/linux-core.c | 33 |
1 files changed, 26 insertions, 7 deletions
diff --git a/deps/uv/src/unix/linux-core.c b/deps/uv/src/unix/linux-core.c index d77b13fd6f..c1be21a8b4 100644 --- a/deps/uv/src/unix/linux-core.c +++ b/deps/uv/src/unix/linux-core.c @@ -74,7 +74,7 @@ static void read_speeds(unsigned int numcpus, uv_cpu_info_t* ci); static unsigned long read_cpufreq(unsigned int cpunum); -int uv__platform_loop_init(uv_loop_t* loop, int default_loop) { +int uv__platform_loop_init(uv_loop_t* loop) { int fd; fd = uv__epoll_create1(UV__EPOLL_CLOEXEC); @@ -136,11 +136,14 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { void uv__io_poll(uv_loop_t* loop, int timeout) { + static int no_epoll_pwait; + static int no_epoll_wait; struct uv__epoll_event events[1024]; struct uv__epoll_event* pe; struct uv__epoll_event e; QUEUE* q; uv__io_t* w; + sigset_t sigset; uint64_t sigmask; uint64_t base; uint64_t diff; @@ -150,7 +153,6 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { int fd; int op; int i; - static int no_epoll_wait; if (loop->nfds == 0) { assert(QUEUE_EMPTY(&loop->watcher_queue)); @@ -193,31 +195,42 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { } sigmask = 0; - if (loop->flags & UV_LOOP_BLOCK_SIGPROF) + if (loop->flags & UV_LOOP_BLOCK_SIGPROF) { + sigemptyset(&sigset); + sigaddset(&sigset, SIGPROF); sigmask |= 1 << (SIGPROF - 1); + } assert(timeout >= -1); base = loop->time; count = 48; /* Benchmarks suggest this gives the best throughput. */ for (;;) { - if (no_epoll_wait || sigmask) { + if (sigmask != 0 && no_epoll_pwait != 0) + if (pthread_sigmask(SIG_BLOCK, &sigset, NULL)) + abort(); + + if (sigmask != 0 && no_epoll_pwait == 0) { nfds = uv__epoll_pwait(loop->backend_fd, events, ARRAY_SIZE(events), timeout, sigmask); + if (nfds == -1 && errno == ENOSYS) + no_epoll_pwait = 1; } else { nfds = uv__epoll_wait(loop->backend_fd, events, ARRAY_SIZE(events), timeout); - if (nfds == -1 && errno == ENOSYS) { + if (nfds == -1 && errno == ENOSYS) no_epoll_wait = 1; - continue; - } } + if (sigmask != 0 && no_epoll_pwait != 0) + if (pthread_sigmask(SIG_UNBLOCK, &sigset, NULL)) + abort(); + /* Update loop->time unconditionally. It's tempting to skip the update when * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the * operating system didn't reschedule our process while in the syscall. @@ -230,6 +243,12 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { } if (nfds == -1) { + if (errno == ENOSYS) { + /* epoll_wait() or epoll_pwait() failed, try the other system call. */ + assert(no_epoll_wait == 0 || no_epoll_pwait == 0); + continue; + } + if (errno != EINTR) abort(); |