summaryrefslogtreecommitdiff
path: root/deps/uv/src/unix/linux-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'deps/uv/src/unix/linux-core.c')
-rw-r--r--deps/uv/src/unix/linux-core.c33
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();