diff --git a/src/node.cc b/src/node.cc index 48ca941f48..8f1589ee64 100644 --- a/src/node.cc +++ b/src/node.cc @@ -17,6 +17,8 @@ #include /* getpwnam() */ #include /* getgrnam() */ +#include "platform.h" + #include #include #include @@ -1232,218 +1234,20 @@ v8::Handle Exit(const v8::Arguments& args) { return Undefined(); } -#ifdef __sun -#define HAVE_GETMEM 1 -#include /* getpagesize() */ - -#if (!defined(_LP64)) && (_FILE_OFFSET_BITS - 0 == 64) -#define PROCFS_FILE_OFFSET_BITS_HACK 1 -#undef _FILE_OFFSET_BITS -#else -#define PROCFS_FILE_OFFSET_BITS_HACK 0 -#endif - -#include - -#if (PROCFS_FILE_OFFSET_BITS_HACK - 0 == 1) -#define _FILE_OFFSET_BITS 64 -#endif - -int getmem(size_t *rss, size_t *vsize) { - pid_t pid = getpid(); - - size_t page_size = getpagesize(); - char pidpath[1024]; - sprintf(pidpath, "/proc/%d/psinfo", pid); - - psinfo_t psinfo; - FILE *f = fopen(pidpath, "r"); - if (!f) return -1; - - if (fread(&psinfo, sizeof(psinfo_t), 1, f) != 1) { - fclose (f); - return -1; - } - - /* XXX correct? */ - - *vsize = (size_t) psinfo.pr_size * page_size; - *rss = (size_t) psinfo.pr_rssize * 1024; - - fclose (f); - - return 0; -} -#endif - - -#ifdef __FreeBSD__ -#define HAVE_GETMEM 1 -#include -#include -#include -#include -#include -#include -#include - -int getmem(size_t *rss, size_t *vsize) { - kvm_t *kd = NULL; - struct kinfo_proc *kinfo = NULL; - pid_t pid; - int nprocs; - size_t page_size = getpagesize(); - - pid = getpid(); - - kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, "kvm_open"); - if (kd == NULL) goto error; - - kinfo = kvm_getprocs(kd, KERN_PROC_PID, pid, &nprocs); - if (kinfo == NULL) goto error; - - *rss = kinfo->ki_rssize * page_size; - *vsize = kinfo->ki_size; - - kvm_close(kd); - - return 0; - -error: - if (kd) kvm_close(kd); - return -1; -} -#endif // __FreeBSD__ - - -#ifdef __APPLE__ -#define HAVE_GETMEM 1 -/* Researched by Tim Becker and Michael Knight - * http://blog.kuriositaet.de/?p=257 - */ - -#include -#include - -int getmem(size_t *rss, size_t *vsize) { - struct task_basic_info t_info; - mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT; - - int r = task_info(mach_task_self(), - TASK_BASIC_INFO, - (task_info_t)&t_info, - &t_info_count); - - if (r != KERN_SUCCESS) return -1; - - *rss = t_info.resident_size; - *vsize = t_info.virtual_size; - - return 0; -} -#endif // __APPLE__ - -#ifdef __linux__ -# define HAVE_GETMEM 1 -# include /* for MAXPATHLEN */ - -int getmem(size_t *rss, size_t *vsize) { - FILE *f = fopen("/proc/self/stat", "r"); - if (!f) return -1; - - int itmp; - char ctmp; - char buffer[MAXPATHLEN]; - size_t page_size = getpagesize(); - - /* PID */ - if (fscanf(f, "%d ", &itmp) == 0) goto error; - /* Exec file */ - if (fscanf (f, "%s ", &buffer[0]) == 0) goto error; - /* State */ - if (fscanf (f, "%c ", &ctmp) == 0) goto error; - /* Parent process */ - if (fscanf (f, "%d ", &itmp) == 0) goto error; - /* Process group */ - if (fscanf (f, "%d ", &itmp) == 0) goto error; - /* Session id */ - if (fscanf (f, "%d ", &itmp) == 0) goto error; - /* TTY */ - if (fscanf (f, "%d ", &itmp) == 0) goto error; - /* TTY owner process group */ - if (fscanf (f, "%d ", &itmp) == 0) goto error; - /* Flags */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; - /* Minor faults (no memory page) */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; - /* Minor faults, children */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; - /* Major faults (memory page faults) */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; - /* Major faults, children */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; - /* utime */ - if (fscanf (f, "%d ", &itmp) == 0) goto error; - /* stime */ - if (fscanf (f, "%d ", &itmp) == 0) goto error; - /* utime, children */ - if (fscanf (f, "%d ", &itmp) == 0) goto error; - /* stime, children */ - if (fscanf (f, "%d ", &itmp) == 0) goto error; - /* jiffies remaining in current time slice */ - if (fscanf (f, "%d ", &itmp) == 0) goto error; - /* 'nice' value */ - if (fscanf (f, "%d ", &itmp) == 0) goto error; - /* jiffies until next timeout */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; - /* jiffies until next SIGALRM */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; - /* start time (jiffies since system boot) */ - if (fscanf (f, "%d ", &itmp) == 0) goto error; - - /* Virtual memory size */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; - *vsize = (size_t) itmp; - - /* Resident set size */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; - *rss = (size_t) itmp * page_size; - - /* rlim */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; - /* Start of text */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; - /* End of text */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; - /* Start of stack */ - if (fscanf (f, "%u ", &itmp) == 0) goto error; - - fclose (f); - - return 0; - -error: - fclose (f); - return -1; -} -#endif // __linux__ - static void CheckStatus(EV_P_ ev_timer *watcher, int revents) { assert(watcher == &gc_timer); assert(revents == EV_TIMEOUT); -#if HAVE_GETMEM // check memory size_t rss, vsize; - if (!ev_is_active(&gc_idle) && getmem(&rss, &vsize) == 0) { + if (!ev_is_active(&gc_idle) && OS::GetMemory(&rss, &vsize) == 0) { if (rss > 1024*1024*128) { // larger than 128 megs, just start the idle watcher ev_idle_start(EV_A_ &gc_idle); return; } } -#endif // HAVE_GETMEM double d = ev_now(EV_DEFAULT_UC) - TICK_TIME(3); @@ -1460,12 +1264,9 @@ v8::Handle MemoryUsage(const v8::Arguments& args) { HandleScope scope; assert(args.Length() == 0); -#ifndef HAVE_GETMEM - return ThrowException(Exception::Error(String::New("Not support on your platform. (Talk to Ryan.)"))); -#else size_t rss, vsize; - int r = getmem(&rss, &vsize); + int r = OS::GetMemory(&rss, &vsize); if (r != 0) { return ThrowException(Exception::Error(String::New(strerror(errno)))); @@ -1492,7 +1293,6 @@ v8::Handle MemoryUsage(const v8::Arguments& args) { Integer::NewFromUnsigned(v8_heap_stats.used_heap_size())); return scope.Close(info); -#endif } diff --git a/src/platform.h b/src/platform.h new file mode 100644 index 0000000000..0b9b9be4ad --- /dev/null +++ b/src/platform.h @@ -0,0 +1,13 @@ +#ifndef NODE_PLATFORM_H_ +#define NODE_PLATFORM_H_ + +namespace node { + +class OS { + public: + static int GetMemory(size_t *rss, size_t *vsize); +}; + + +} // namespace node +#endif // NODE_PLATFORM_H_ diff --git a/src/platform_darwin.cc b/src/platform_darwin.cc new file mode 100644 index 0000000000..a1bcc107c4 --- /dev/null +++ b/src/platform_darwin.cc @@ -0,0 +1,29 @@ +#include "node.h" +#include "platform.h" + +#include +#include + +namespace node { + +// Researched by Tim Becker and Michael Knight +// http://blog.kuriositaet.de/?p=257 +int OS::GetMemory(size_t *rss, size_t *vsize) { + struct task_basic_info t_info; + mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT; + + int r = task_info(mach_task_self(), + TASK_BASIC_INFO, + (task_info_t)&t_info, + &t_info_count); + + if (r != KERN_SUCCESS) return -1; + + *rss = t_info.resident_size; + *vsize = t_info.virtual_size; + + return 0; +} + + +} // namespace node diff --git a/src/platform_freebsd.cc b/src/platform_freebsd.cc new file mode 100644 index 0000000000..514b796a8f --- /dev/null +++ b/src/platform_freebsd.cc @@ -0,0 +1,45 @@ +#include "node.h" +#include "platform.h" + +#include +#include +#include +#include +#include +#include +#include + + +namespace node { + + +int OS::GetMemory(size_t *rss, size_t *vsize) { + kvm_t *kd = NULL; + struct kinfo_proc *kinfo = NULL; + pid_t pid; + int nprocs; + size_t page_size = getpagesize(); + + pid = getpid(); + + kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, "kvm_open"); + if (kd == NULL) goto error; + + kinfo = kvm_getprocs(kd, KERN_PROC_PID, pid, &nprocs); + if (kinfo == NULL) goto error; + + *rss = kinfo->ki_rssize * page_size; + *vsize = kinfo->ki_size; + + kvm_close(kd); + + return 0; + +error: + if (kd) kvm_close(kd); + return -1; +} + + + +} // namespace node diff --git a/src/platform_linux.cc b/src/platform_linux.cc new file mode 100644 index 0000000000..2e2f246ca6 --- /dev/null +++ b/src/platform_linux.cc @@ -0,0 +1,91 @@ +#include "node.h" +#include "platform.h" + +# include /* for MAXPATHLEN */ + + +namespace node { + + +int OS::GetMemory(size_t *rss, size_t *vsize) { + FILE *f = fopen("/proc/self/stat", "r"); + if (!f) return -1; + + int itmp; + char ctmp; + char buffer[MAXPATHLEN]; + size_t page_size = getpagesize(); + + /* PID */ + if (fscanf(f, "%d ", &itmp) == 0) goto error; + /* Exec file */ + if (fscanf (f, "%s ", &buffer[0]) == 0) goto error; + /* State */ + if (fscanf (f, "%c ", &ctmp) == 0) goto error; + /* Parent process */ + if (fscanf (f, "%d ", &itmp) == 0) goto error; + /* Process group */ + if (fscanf (f, "%d ", &itmp) == 0) goto error; + /* Session id */ + if (fscanf (f, "%d ", &itmp) == 0) goto error; + /* TTY */ + if (fscanf (f, "%d ", &itmp) == 0) goto error; + /* TTY owner process group */ + if (fscanf (f, "%d ", &itmp) == 0) goto error; + /* Flags */ + if (fscanf (f, "%u ", &itmp) == 0) goto error; + /* Minor faults (no memory page) */ + if (fscanf (f, "%u ", &itmp) == 0) goto error; + /* Minor faults, children */ + if (fscanf (f, "%u ", &itmp) == 0) goto error; + /* Major faults (memory page faults) */ + if (fscanf (f, "%u ", &itmp) == 0) goto error; + /* Major faults, children */ + if (fscanf (f, "%u ", &itmp) == 0) goto error; + /* utime */ + if (fscanf (f, "%d ", &itmp) == 0) goto error; + /* stime */ + if (fscanf (f, "%d ", &itmp) == 0) goto error; + /* utime, children */ + if (fscanf (f, "%d ", &itmp) == 0) goto error; + /* stime, children */ + if (fscanf (f, "%d ", &itmp) == 0) goto error; + /* jiffies remaining in current time slice */ + if (fscanf (f, "%d ", &itmp) == 0) goto error; + /* 'nice' value */ + if (fscanf (f, "%d ", &itmp) == 0) goto error; + /* jiffies until next timeout */ + if (fscanf (f, "%u ", &itmp) == 0) goto error; + /* jiffies until next SIGALRM */ + if (fscanf (f, "%u ", &itmp) == 0) goto error; + /* start time (jiffies since system boot) */ + if (fscanf (f, "%d ", &itmp) == 0) goto error; + + /* Virtual memory size */ + if (fscanf (f, "%u ", &itmp) == 0) goto error; + *vsize = (size_t) itmp; + + /* Resident set size */ + if (fscanf (f, "%u ", &itmp) == 0) goto error; + *rss = (size_t) itmp * page_size; + + /* rlim */ + if (fscanf (f, "%u ", &itmp) == 0) goto error; + /* Start of text */ + if (fscanf (f, "%u ", &itmp) == 0) goto error; + /* End of text */ + if (fscanf (f, "%u ", &itmp) == 0) goto error; + /* Start of stack */ + if (fscanf (f, "%u ", &itmp) == 0) goto error; + + fclose (f); + + return 0; + +error: + fclose (f); + return -1; +} + + +} // namespace node diff --git a/src/platform_sunos.cc b/src/platform_sunos.cc new file mode 100644 index 0000000000..d370dea6e8 --- /dev/null +++ b/src/platform_sunos.cc @@ -0,0 +1,52 @@ +#include "node.h" +#include "platform.h" + + +#include /* getpagesize() */ + +#if (!defined(_LP64)) && (_FILE_OFFSET_BITS - 0 == 64) +#define PROCFS_FILE_OFFSET_BITS_HACK 1 +#undef _FILE_OFFSET_BITS +#else +#define PROCFS_FILE_OFFSET_BITS_HACK 0 +#endif + +#include + +#if (PROCFS_FILE_OFFSET_BITS_HACK - 0 == 1) +#define _FILE_OFFSET_BITS 64 +#endif + + +namespace node { + + +int OS::GetMemory(size_t *rss, size_t *vsize) { + pid_t pid = getpid(); + + size_t page_size = getpagesize(); + char pidpath[1024]; + sprintf(pidpath, "/proc/%d/psinfo", pid); + + psinfo_t psinfo; + FILE *f = fopen(pidpath, "r"); + if (!f) return -1; + + if (fread(&psinfo, sizeof(psinfo_t), 1, f) != 1) { + fclose (f); + return -1; + } + + /* XXX correct? */ + + *vsize = (size_t) psinfo.pr_size * page_size; + *rss = (size_t) psinfo.pr_rssize * 1024; + + fclose (f); + + return 0; +} + + +} // namespace node + diff --git a/wscript b/wscript index 9efca2fdfa..9516245198 100644 --- a/wscript +++ b/wscript @@ -16,7 +16,6 @@ srcdir = '.' blddir = 'build' - jobs=1 if os.environ.has_key('JOBS'): jobs = int(os.environ['JOBS']) @@ -278,7 +277,7 @@ def configure(conf): conf.env.append_value('CXXFLAGS', '-DHAVE_FDATASYNC=0') # platform - platform_def = '-DPLATFORM=' + sys.platform + platform_def = '-DPLATFORM=' + conf.env['DEST_OS'] conf.env.append_value('CCFLAGS', platform_def) conf.env.append_value('CXXFLAGS', platform_def) @@ -468,7 +467,15 @@ def build(bld): src/node_timer.cc src/node_script.cc """ - if bld.env["USE_OPENSSL"]: node.source += "src/node_crypto.cc" + + platform_file = "src/platform_%s.cc" % bld.env['DEST_OS'] + if os.path.exists(join(cwd, platform_file)): + node.source += platform_file + else: + node.source += "src/platform_none.cc " + + + if bld.env["USE_OPENSSL"]: node.source += " src/node_crypto.cc " node.includes = """ src/