diff --git a/src/platform_sunos.cc b/src/platform_sunos.cc index dc9617e047..002b373a5a 100644 --- a/src/platform_sunos.cc +++ b/src/platform_sunos.cc @@ -27,6 +27,10 @@ #include /* getexecname() */ #include /* strncpy() */ +#include +#include +#include +#include #if (!defined(_LP64)) && (_FILE_OFFSET_BITS - 0 == 64) #define PROCFS_FILE_OFFSET_BITS_HACK 1 @@ -46,6 +50,7 @@ namespace node { using namespace v8; + char** Platform::SetupArgs(int argc, char *argv[]) { return argv; } @@ -108,11 +113,103 @@ int Platform::GetExecutablePath(char* buffer, size_t* size) { } -// TODO: libkstat provides all this info. Need to link it though. +static Handle data_named(kstat_named_t *knp) { + Handle val; + + switch (knp->data_type) { + case KSTAT_DATA_CHAR: + val = Number::New(knp->value.c[0]); + break; + case KSTAT_DATA_INT32: + val = Number::New(knp->value.i32); + break; + case KSTAT_DATA_UINT32: + val = Number::New(knp->value.ui32); + break; + case KSTAT_DATA_INT64: + val = Number::New(knp->value.i64); + break; + case KSTAT_DATA_UINT64: + val = Number::New(knp->value.ui64); + break; + case KSTAT_DATA_STRING: + val = String::New(KSTAT_NAMED_STR_PTR(knp)); + break; + default: + throw (String::New("unrecognized data type")); + } + + return (val); +} int Platform::GetCPUInfo(Local *cpus) { - // http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/cmd/psrinfo/psrinfo.pl + HandleScope scope; + Local cpuinfo; + Local cputimes; + + int lookup_instance; + kstat_ctl_t *kc; + kstat_t *ksp; + kstat_named_t *knp; + + if ((kc = kstat_open()) == NULL) + throw "could not open kstat"; + + *cpus = Array::New(); + + lookup_instance = 0; + while (ksp = kstat_lookup(kc, "cpu_info", lookup_instance, NULL)){ + cpuinfo = Object::New(); + + if (kstat_read(kc, ksp, NULL) == -1) { + /* + * It is deeply annoying, but some kstats can return errors + * under otherwise routine conditions. (ACPI is one + * offender; there are surely others.) To prevent these + * fouled kstats from completely ruining our day, we assign + * an "error" member to the return value that consists of + * the strerror(). + */ + cpuinfo->Set(String::New("error"), String::New(strerror(errno))); + (*cpus)->Set(lookup_instance, cpuinfo); + } else { + knp = (kstat_named_t *) kstat_data_lookup(ksp, "clock_MHz"); + cpuinfo->Set(String::New("speed"), data_named(knp)); + knp = (kstat_named_t *) kstat_data_lookup(ksp, "brand"); + cpuinfo->Set(String::New("model"), data_named(knp)); + (*cpus)->Set(lookup_instance, cpuinfo); + } + + lookup_instance++; + } + + lookup_instance = 0; + while (ksp = kstat_lookup(kc, "cpu", lookup_instance, "sys")){ + cpuinfo = (*cpus)->Get(lookup_instance)->ToObject(); + cputimes = Object::New(); + + if (kstat_read(kc, ksp, NULL) == -1) { + cputimes->Set(String::New("error"), String::New(strerror(errno))); + cpuinfo->Set(String::New("times"), cpuinfo); + } else { + knp = (kstat_named_t *) kstat_data_lookup(ksp, "cpu_ticks_kernel"); + cputimes->Set(String::New("system"), data_named(knp)); + knp = (kstat_named_t *) kstat_data_lookup(ksp, "cpu_ticks_user"); + cputimes->Set(String::New("user"), data_named(knp)); + knp = (kstat_named_t *) kstat_data_lookup(ksp, "cpu_ticks_idle"); + cputimes->Set(String::New("idle"), data_named(knp)); + knp = (kstat_named_t *) kstat_data_lookup(ksp, "intr"); + cputimes->Set(String::New("irq"), data_named(knp)); + + cpuinfo->Set(String::New("times"), cputimes); + } + + lookup_instance++; + } + + kstat_close(kc); + return 0; } @@ -126,12 +223,30 @@ double Platform::GetTotalMemory() { return 0.0; } - double Platform::GetUptime() { - // http://munin-monitoring.org/attachment/ticket/419/uptime - return 0.0; -} + kstat_ctl_t *kc; + kstat_t *ksp; + kstat_named_t *knp; + + long hz = sysconf(_SC_CLK_TCK); + ulong_t clk_intr; + + if ((kc = kstat_open()) == NULL) + throw "could not open kstat"; + + ksp = kstat_lookup(kc, "unix", 0, "system_misc"); + if (kstat_read(kc, ksp, NULL) == -1) { + throw "unable to read kstat"; + } else { + knp = (kstat_named_t *) kstat_data_lookup(ksp, "clk_intr"); + clk_intr = knp->value.ul; + } + + kstat_close(kc); + + return static_cast( clk_intr / hz ); +} int Platform::GetLoadAvg(Local *loads) { return 0; diff --git a/test/simple/test-os.js b/test/simple/test-os.js index 5903f8f6b1..b43d339139 100644 --- a/test/simple/test-os.js +++ b/test/simple/test-os.js @@ -23,11 +23,29 @@ var common = require('../common'); var assert = require('assert'); var os = require('os'); -assert.ok(os.hostname().length > 0); -assert.ok(os.loadavg().length > 0); -assert.ok(os.uptime() > 0); -assert.ok(os.freemem() > 0); -assert.ok(os.totalmem() > 0); -assert.ok(os.cpus().length > 0); -assert.ok(os.type().length > 0); -assert.ok(os.release().length > 0); \ No newline at end of file +var hostname = os.hostname() +console.log("hostname = %s", hostname); +assert.ok(hostname.length > 0); + +var uptime = os.uptime(); +console.log("uptime = %d", uptime); +assert.ok(uptime > 0); + +var cpus = os.cpus(); +console.log("cpus = ", cpus); +assert.ok(cpus.length > 0); + +var type = os.type(); +console.log("type = ", type); +assert.ok(type.length > 0); + +var release = os.release(); +console.log("release = ", release); +assert.ok(release.length > 0); + +if (process.platform != 'sunos') { + // not implemeneted yet + assert.ok(os.loadavg().length > 0); + assert.ok(os.freemem() > 0); + assert.ok(os.totalmem() > 0); +} diff --git a/wscript b/wscript index 7692e83f4e..756b530cf8 100644 --- a/wscript +++ b/wscript @@ -359,6 +359,8 @@ def configure(conf): conf.fatal("Cannot find socket library") if not conf.check(lib='nsl', uselib_store="NSL"): conf.fatal("Cannot find nsl library") + if not conf.check(lib='kstat', uselib_store="KSTAT"): + conf.fatal("Cannot find kstat library") conf.sub_config('deps/libeio') @@ -802,7 +804,7 @@ def build(bld): node = bld.new_task_gen("cxx", product_type) node.name = "node" node.target = "node" - node.uselib = 'RT EV OPENSSL CARES EXECINFO DL KVM SOCKET NSL UTIL OPROFILE' + node.uselib = 'RT EV OPENSSL CARES EXECINFO DL KVM SOCKET NSL KSTAT UTIL OPROFILE' node.add_objects = 'eio http_parser' if product_type_is_lib: node.install_path = '${LIBDIR}'