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.c156
1 files changed, 138 insertions, 18 deletions
diff --git a/deps/uv/src/unix/linux-core.c b/deps/uv/src/unix/linux-core.c
index f8973bb36b..b539beb86a 100644
--- a/deps/uv/src/unix/linux-core.c
+++ b/deps/uv/src/unix/linux-core.c
@@ -26,6 +26,7 @@
#include "uv.h"
#include "internal.h"
+#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -79,16 +80,20 @@ static int read_times(FILE* statfile_fp,
unsigned int numcpus,
uv_cpu_info_t* ci);
static void read_speeds(unsigned int numcpus, uv_cpu_info_t* ci);
-static unsigned long read_cpufreq(unsigned int cpunum);
+static uint64_t read_cpufreq(unsigned int cpunum);
int uv__platform_loop_init(uv_loop_t* loop) {
int fd;
- fd = epoll_create1(EPOLL_CLOEXEC);
+ /* It was reported that EPOLL_CLOEXEC is not defined on Android API < 21,
+ * a.k.a. Lollipop. Since EPOLL_CLOEXEC is an alias for O_CLOEXEC on all
+ * architectures, we just use that instead.
+ */
+ fd = epoll_create1(O_CLOEXEC);
/* epoll_create1() can fail either because it's not implemented (old kernel)
- * or because it doesn't understand the EPOLL_CLOEXEC flag.
+ * or because it doesn't understand the O_CLOEXEC flag.
*/
if (fd == -1 && (errno == ENOSYS || errno == EINVAL)) {
fd = epoll_create(256);
@@ -715,20 +720,20 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) {
static int read_times(FILE* statfile_fp,
unsigned int numcpus,
uv_cpu_info_t* ci) {
- unsigned long clock_ticks;
struct uv_cpu_times_s ts;
- unsigned long user;
- unsigned long nice;
- unsigned long sys;
- unsigned long idle;
- unsigned long dummy;
- unsigned long irq;
- unsigned int num;
- unsigned int len;
+ uint64_t clock_ticks;
+ uint64_t user;
+ uint64_t nice;
+ uint64_t sys;
+ uint64_t idle;
+ uint64_t dummy;
+ uint64_t irq;
+ uint64_t num;
+ uint64_t len;
char buf[1024];
clock_ticks = sysconf(_SC_CLK_TCK);
- assert(clock_ticks != (unsigned long) -1);
+ assert(clock_ticks != (uint64_t) -1);
assert(clock_ticks != 0);
rewind(statfile_fp);
@@ -761,7 +766,8 @@ static int read_times(FILE* statfile_fp,
* fields, they're not allowed in C89 mode.
*/
if (6 != sscanf(buf + len,
- "%lu %lu %lu %lu %lu %lu",
+ "%" PRIu64 " %" PRIu64 " %" PRIu64
+ "%" PRIu64 " %" PRIu64 " %" PRIu64,
&user,
&nice,
&sys,
@@ -783,8 +789,8 @@ static int read_times(FILE* statfile_fp,
}
-static unsigned long read_cpufreq(unsigned int cpunum) {
- unsigned long val;
+static uint64_t read_cpufreq(unsigned int cpunum) {
+ uint64_t val;
char buf[1024];
FILE* fp;
@@ -797,7 +803,7 @@ static unsigned long read_cpufreq(unsigned int cpunum) {
if (fp == NULL)
return 0;
- if (fscanf(fp, "%lu", &val) != 1)
+ if (fscanf(fp, "%" PRIu64, &val) != 1)
val = 0;
fclose(fp);
@@ -900,7 +906,10 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
address = *addresses;
for (i = 0; i < (*count); i++) {
- if (strcmp(address->name, ent->ifa_name) == 0) {
+ size_t namelen = strlen(ent->ifa_name);
+ /* Alias interface share the same physical address */
+ if (strncmp(address->name, ent->ifa_name, namelen) == 0 &&
+ (address->name[namelen] == 0 || address->name[namelen] == ':')) {
sll = (struct sockaddr_ll*)ent->ifa_addr;
memcpy(address->phys_addr, sll->sll_addr, sizeof(address->phys_addr));
}
@@ -932,3 +941,114 @@ void uv__set_process_title(const char* title) {
prctl(PR_SET_NAME, title); /* Only copies first 16 characters. */
#endif
}
+
+
+static uint64_t uv__read_proc_meminfo(const char* what) {
+ uint64_t rc;
+ ssize_t n;
+ char* p;
+ int fd;
+ char buf[4096]; /* Large enough to hold all of /proc/meminfo. */
+
+ rc = 0;
+ fd = uv__open_cloexec("/proc/meminfo", O_RDONLY);
+
+ if (fd == -1)
+ return 0;
+
+ n = read(fd, buf, sizeof(buf) - 1);
+
+ if (n <= 0)
+ goto out;
+
+ buf[n] = '\0';
+ p = strstr(buf, what);
+
+ if (p == NULL)
+ goto out;
+
+ p += strlen(what);
+
+ if (1 != sscanf(p, "%" PRIu64 " kB", &rc))
+ goto out;
+
+ rc *= 1024;
+
+out:
+
+ if (uv__close_nocheckstdio(fd))
+ abort();
+
+ return rc;
+}
+
+
+uint64_t uv_get_free_memory(void) {
+ struct sysinfo info;
+ uint64_t rc;
+
+ rc = uv__read_proc_meminfo("MemFree:");
+
+ if (rc != 0)
+ return rc;
+
+ if (0 == sysinfo(&info))
+ return (uint64_t) info.freeram * info.mem_unit;
+
+ return 0;
+}
+
+
+uint64_t uv_get_total_memory(void) {
+ struct sysinfo info;
+ uint64_t rc;
+
+ rc = uv__read_proc_meminfo("MemTotal:");
+
+ if (rc != 0)
+ return rc;
+
+ if (0 == sysinfo(&info))
+ return (uint64_t) info.totalram * info.mem_unit;
+
+ return 0;
+}
+
+
+static uint64_t uv__read_cgroups_uint64(const char* cgroup, const char* param) {
+ char filename[256];
+ uint64_t rc;
+ int fd;
+ ssize_t n;
+ char buf[32]; /* Large enough to hold an encoded uint64_t. */
+
+ snprintf(filename, 256, "/sys/fs/cgroup/%s/%s", cgroup, param);
+
+ rc = 0;
+ fd = uv__open_cloexec(filename, O_RDONLY);
+
+ if (fd < 0)
+ return 0;
+
+ n = read(fd, buf, sizeof(buf) - 1);
+
+ if (n > 0) {
+ buf[n] = '\0';
+ sscanf(buf, "%" PRIu64, &rc);
+ }
+
+ if (uv__close_nocheckstdio(fd))
+ abort();
+
+ return rc;
+}
+
+
+uint64_t uv_get_constrained_memory(void) {
+ /*
+ * This might return 0 if there was a problem getting the memory limit from
+ * cgroups. This is OK because a return value of 0 signifies that the memory
+ * limit is unknown.
+ */
+ return uv__read_cgroups_uint64("memory", "memory.limit_in_bytes");
+}