summaryrefslogtreecommitdiffstats
path: root/src/unix/linux-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/unix/linux-core.c')
-rw-r--r--src/unix/linux-core.c81
1 files changed, 59 insertions, 22 deletions
diff --git a/src/unix/linux-core.c b/src/unix/linux-core.c
index b539beb..f8d9ff5 100644
--- a/src/unix/linux-core.c
+++ b/src/unix/linux-core.c
@@ -90,7 +90,12 @@ int uv__platform_loop_init(uv_loop_t* loop) {
* a.k.a. Lollipop. Since EPOLL_CLOEXEC is an alias for O_CLOEXEC on all
* architectures, we just use that instead.
*/
+#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
+ fd = -1;
+ errno = ENOSYS;
+#else
fd = epoll_create1(O_CLOEXEC);
+#endif
/* epoll_create1() can fail either because it's not implemented (old kernel)
* or because it doesn't understand the O_CLOEXEC flag.
@@ -203,6 +208,8 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
* that being the largest value I have seen in the wild (and only once.)
*/
static const int max_safe_timeout = 1789569;
+ static int no_epoll_pwait;
+ static int no_epoll_wait;
struct epoll_event events[1024];
struct epoll_event* pe;
struct epoll_event e;
@@ -210,7 +217,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
QUEUE* q;
uv__io_t* w;
sigset_t sigset;
- sigset_t* psigset;
+ uint64_t sigmask;
uint64_t base;
int have_signals;
int nevents;
@@ -262,11 +269,11 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
w->events = w->pevents;
}
- psigset = NULL;
+ sigmask = 0;
if (loop->flags & UV_LOOP_BLOCK_SIGPROF) {
sigemptyset(&sigset);
sigaddset(&sigset, SIGPROF);
- psigset = &sigset;
+ sigmask |= 1 << (SIGPROF - 1);
}
assert(timeout >= -1);
@@ -281,11 +288,35 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
if (sizeof(int32_t) == sizeof(long) && timeout >= max_safe_timeout)
timeout = max_safe_timeout;
- nfds = epoll_pwait(loop->backend_fd,
- events,
- ARRAY_SIZE(events),
- timeout,
- psigset);
+ if (sigmask != 0 && no_epoll_pwait != 0)
+ if (pthread_sigmask(SIG_BLOCK, &sigset, NULL))
+ abort();
+
+ if (no_epoll_wait != 0 || (sigmask != 0 && no_epoll_pwait == 0)) {
+#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
+ nfds = -1;
+ errno = ENOSYS;
+#else
+ nfds = epoll_pwait(loop->backend_fd,
+ events,
+ ARRAY_SIZE(events),
+ timeout,
+ &sigset);
+#endif
+ if (nfds == -1 && errno == ENOSYS)
+ no_epoll_pwait = 1;
+ } else {
+ nfds = epoll_wait(loop->backend_fd,
+ events,
+ ARRAY_SIZE(events),
+ timeout);
+ if (nfds == -1 && errno == ENOSYS)
+ no_epoll_wait = 1;
+ }
+
+ 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
@@ -306,6 +337,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();
@@ -322,9 +359,19 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
have_signals = 0;
nevents = 0;
- assert(loop->watchers != NULL);
- loop->watchers[loop->nwatchers] = (void*) events;
- loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds;
+ {
+ /* Squelch a -Waddress-of-packed-member warning with gcc >= 9. */
+ union {
+ struct epoll_event* events;
+ uv__io_t* watchers;
+ } x;
+
+ x.events = events;
+ assert(loop->watchers != NULL);
+ loop->watchers[loop->nwatchers] = x.watchers;
+ loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds;
+ }
+
for (i = 0; i < nfds; i++) {
pe = events + i;
fd = pe->data.fd;
@@ -812,16 +859,6 @@ static uint64_t read_cpufreq(unsigned int cpunum) {
}
-void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
- int i;
-
- for (i = 0; i < count; i++) {
- uv__free(cpu_infos[i].model);
- }
-
- uv__free(cpu_infos);
-}
-
static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
return 1;
@@ -953,7 +990,7 @@ static uint64_t uv__read_proc_meminfo(const char* what) {
rc = 0;
fd = uv__open_cloexec("/proc/meminfo", O_RDONLY);
- if (fd == -1)
+ if (fd < 0)
return 0;
n = read(fd, buf, sizeof(buf) - 1);