diff --git a/config-unix.mk b/config-unix.mk index 59bf8f17..6ff4574b 100644 --- a/config-unix.mk +++ b/config-unix.mk @@ -44,7 +44,7 @@ ifeq (SunOS,$(uname_S)) EV_CONFIG=config_sunos.h EIO_CONFIG=config_sunos.h CPPFLAGS += -Isrc/ares/config_sunos -D__EXTENSIONS__ -D_XOPEN_SOURCE=500 -LINKFLAGS+=-lsocket -lnsl +LINKFLAGS+=-lsocket -lnsl -lkstat OBJS += src/unix/sunos.o endif diff --git a/include/uv.h b/include/uv.h index 348abe3f..aad594e1 100644 --- a/include/uv.h +++ b/include/uv.h @@ -1065,6 +1065,10 @@ int uv_ip6_name(struct sockaddr_in6* src, char* dst, size_t size); /* Gets the executable path */ int uv_exepath(char* buffer, size_t* size); +/* Memory info */ +double uv_get_free_memory(void); +double uv_get_total_memory(void); + /* * Returns the current high-resolution real time. This is expressed in * nanoseconds. It is relative to an arbitrary time in the past. It is not diff --git a/src/unix/cygwin.c b/src/unix/cygwin.c index 91681248..418336d6 100644 --- a/src/unix/cygwin.c +++ b/src/unix/cygwin.c @@ -53,6 +53,13 @@ int uv_exepath(char* buffer, size_t* size) { return 0; } +double uv_get_free_memory(void) { + return (double) sysconf(_SC_PAGESIZE) * sysconf(_SC_AVPHYS_PAGES); +} + +double uv_get_total_memory(void) { + return (double) sysconf(_SC_PAGESIZE) * sysconf(_SC_PHYS_PAGES); +} int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle, diff --git a/src/unix/darwin.c b/src/unix/darwin.c index fde51544..b912139e 100644 --- a/src/unix/darwin.c +++ b/src/unix/darwin.c @@ -68,6 +68,30 @@ int uv_exepath(char* buffer, size_t* size) { return 0; } +double uv_get_free_memory(void) { + vm_statistics_data_t info; + mach_msg_type_number_t count = sizeof(info) / sizeof(integer_t); + + if (host_statistics(mach_host_self(), HOST_VM_INFO, + (host_info_t)&info, &count) != KERN_SUCCESS) { + return -1; + } + + return (double) info.free_count * sysconf(_SC_PAGESIZE); +} + +double uv_get_total_memory(void) { + uint64_t info; + int which[] = {CTL_HW, HW_MEMSIZE}; + size_t size = sizeof(info); + + if (sysctl(which, 2, &info, &size, NULL, 0) < 0) { + return -1; + } + + return (double) info; +} + int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle, diff --git a/src/unix/freebsd.c b/src/unix/freebsd.c index cd1959a4..9dbb2b31 100644 --- a/src/unix/freebsd.c +++ b/src/unix/freebsd.c @@ -67,6 +67,31 @@ int uv_exepath(char* buffer, size_t* size) { return 0; } +double uv_get_free_memory(void) { + vm_statistics_data_t info; + mach_msg_type_number_t count = sizeof(info) / sizeof(integer_t); + + if (host_statistics(mach_host_self(), HOST_VM_INFO, + (host_info_t)&info, &count) != KERN_SUCCESS) { + return -1; + } + + return (double) info.free_count * sysconf(_SC_PAGESIZE); +} + +double uv_get_total_memory(void) { + unsigned long info; + int which[] = {CTL_HW, HW_PHYSMEM}; + + size_t size = sizeof(info); + + if (sysctl(which, 2, &info, &size, NULL, 0) < 0) { + return -1; + } + + return (double) info; +} + int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle, diff --git a/src/unix/linux.c b/src/unix/linux.c index dd93e595..0a176286 100644 --- a/src/unix/linux.c +++ b/src/unix/linux.c @@ -64,6 +64,13 @@ int uv_exepath(char* buffer, size_t* size) { return 0; } +double uv_get_free_memory(void) { + return (double) sysconf(_SC_PAGESIZE) * sysconf(_SC_AVPHYS_PAGES); +} + +double uv_get_total_memory(void) { + return (double) sysconf(_SC_PAGESIZE) * sysconf(_SC_PHYS_PAGES); +} static int new_inotify_fd(void) { #if defined(IN_NONBLOCK) && defined(IN_CLOEXEC) diff --git a/src/unix/netbsd.c b/src/unix/netbsd.c index 0483b5e6..5db3285c 100644 --- a/src/unix/netbsd.c +++ b/src/unix/netbsd.c @@ -70,6 +70,34 @@ int uv_exepath(char* buffer, size_t* size) { return 0; } +double uv_get_free_memory(void) { + struct uvmexp info; + size_t size = sizeof(info); + int which[] = {CTL_VM, VM_UVMEXP}; + + if (sysctl(which, 2, &info, &size, NULL, 0) < 0) { + return -1; + } + + return (double) info.free * psysconf(_SC_PAGESIZE); +} + +double uv_get_total_memory(void) { +#if defined(HW_PHYSMEM64) + uint64_t info; + int which[] = {CTL_HW, HW_PHYSMEM64}; +#else + unsigned int info; + int which[] = {CTL_HW, HW_PHYSMEM}; +#endif + size_t size = sizeof(info); + + if (sysctl(which, 2, &info, &size, NULL, 0) < 0) { + return -1; + } + + return (double) info; +} int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle, diff --git a/src/unix/sunos.c b/src/unix/sunos.c index c56b7dc5..ecfdbf7d 100644 --- a/src/unix/sunos.c +++ b/src/unix/sunos.c @@ -28,6 +28,7 @@ #include #include +#include uint64_t uv_hrtime() { @@ -63,6 +64,35 @@ int uv_exepath(char* buffer, size_t* size) { return (0); } +double uv_get_free_memory(void) { + kstat_ctl_t *kc; + kstat_t *ksp; + kstat_named_t *knp; + + ulong_t freemem; + + if ((kc = kstat_open()) == NULL) return -1; + + ksp = kstat_lookup(kc, (char *)"unix", 0, (char *)"system_pages"); + + if(kstat_read(kc, ksp, NULL) == -1){ + return -1; + } + else { + knp = (kstat_named_t *) kstat_data_lookup(ksp, (char *)"freemem"); + freemem = knp->value.ul; + } + + kstat_close(kc); + + return (double) freemem * sysconf(_SC_PAGESIZE); +} + + +double uv_get_total_memory(void) { + return (double) sysconf(_SC_PAGESIZE) * sysconf(_SC_PHYS_PAGES); +} + int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle, diff --git a/src/win/util.c b/src/win/util.c index c57a7298..5db0ad78 100644 --- a/src/win/util.c +++ b/src/win/util.c @@ -94,3 +94,27 @@ done: return retVal; } + +double uv_get_free_memory(void) { + MEMORYSTATUSEX memory_status; + memory_status.dwLength = sizeof(memory_status); + + if(!GlobalMemoryStatusEx(&memory_status)) + { + return -1; + } + + return (double)memory_status.ullAvailPhys; +} + +double uv_get_total_memory(void) { + MEMORYSTATUSEX memory_status; + memory_status.dwLength = sizeof(memory_status); + + if(!GlobalMemoryStatusEx(&memory_status)) + { + return -1; + } + + return (double)memory_status.ullTotalPhys; +} diff --git a/test/test-get-memory.c b/test/test-get-memory.c new file mode 100644 index 00000000..64b9e0dd --- /dev/null +++ b/test/test-get-memory.c @@ -0,0 +1,34 @@ +/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "task.h" + +TEST_IMPL(get_memory) { + double free_mem = uv_get_free_memory(); + double total_mem = uv_get_total_memory(); + + ASSERT(free_mem > 0); + ASSERT(total_mem > 0); + ASSERT(total_mem > free_mem); + + return 0; +} diff --git a/test/test-list.h b/test/test-list.h index dcc56076..4ff07bd4 100644 --- a/test/test-list.h +++ b/test/test-list.h @@ -67,6 +67,7 @@ TEST_DECLARE (check_ref) TEST_DECLARE (unref_in_prepare_cb) TEST_DECLARE (async) TEST_DECLARE (get_currentexe) +TEST_DECLARE (get_memory) TEST_DECLARE (hrtime) TEST_DECLARE (getaddrinfo_basic) TEST_DECLARE (getaddrinfo_concurrent) @@ -185,6 +186,8 @@ TASK_LIST_START TEST_ENTRY (get_currentexe) + TEST_ENTRY (get_memory) + TEST_ENTRY (hrtime) TEST_ENTRY (getaddrinfo_basic) diff --git a/uv.gyp b/uv.gyp index 3377c9de..02fadbd3 100644 --- a/uv.gyp +++ b/uv.gyp @@ -250,6 +250,7 @@ 'test/test-fs.c', 'test/test-fs-event.c', 'test/test-get-currentexe.c', + 'test/test-get-memory.c', 'test/test-getaddrinfo.c', 'test/test-gethostbyname.c', 'test/test-getsockname.c',