Skip to content

Commit 90348a6

Browse files
Scott McWhirterry
Scott McWhirter
authored andcommitted
Add os.cpus() and os.uptime() support for sunos
1 parent 2f98451 commit 90348a6

File tree

3 files changed

+150
-15
lines changed

3 files changed

+150
-15
lines changed

src/platform_sunos.cc

+121-6
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@
2727
#include <stdlib.h> /* getexecname() */
2828
#include <strings.h> /* strncpy() */
2929

30+
#include <kstat.h>
31+
#include <errno.h>
32+
#include <inttypes.h>
33+
#include <sys/types.h>
3034

3135
#if (!defined(_LP64)) && (_FILE_OFFSET_BITS - 0 == 64)
3236
#define PROCFS_FILE_OFFSET_BITS_HACK 1
@@ -46,6 +50,7 @@ namespace node {
4650

4751
using namespace v8;
4852

53+
4954
char** Platform::SetupArgs(int argc, char *argv[]) {
5055
return argv;
5156
}
@@ -108,11 +113,103 @@ int Platform::GetExecutablePath(char* buffer, size_t* size) {
108113
}
109114

110115

111-
// TODO: libkstat provides all this info. Need to link it though.
116+
static Handle<Value> data_named(kstat_named_t *knp) {
117+
Handle<Value> val;
118+
119+
switch (knp->data_type) {
120+
case KSTAT_DATA_CHAR:
121+
val = Number::New(knp->value.c[0]);
122+
break;
123+
case KSTAT_DATA_INT32:
124+
val = Number::New(knp->value.i32);
125+
break;
126+
case KSTAT_DATA_UINT32:
127+
val = Number::New(knp->value.ui32);
128+
break;
129+
case KSTAT_DATA_INT64:
130+
val = Number::New(knp->value.i64);
131+
break;
132+
case KSTAT_DATA_UINT64:
133+
val = Number::New(knp->value.ui64);
134+
break;
135+
case KSTAT_DATA_STRING:
136+
val = String::New(KSTAT_NAMED_STR_PTR(knp));
137+
break;
138+
default:
139+
throw (String::New("unrecognized data type"));
140+
}
141+
142+
return (val);
143+
}
112144

113145

114146
int Platform::GetCPUInfo(Local<Array> *cpus) {
115-
// http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/cmd/psrinfo/psrinfo.pl
147+
HandleScope scope;
148+
Local<Object> cpuinfo;
149+
Local<Object> cputimes;
150+
151+
int lookup_instance;
152+
kstat_ctl_t *kc;
153+
kstat_t *ksp;
154+
kstat_named_t *knp;
155+
156+
if ((kc = kstat_open()) == NULL)
157+
throw "could not open kstat";
158+
159+
*cpus = Array::New();
160+
161+
lookup_instance = 0;
162+
while (ksp = kstat_lookup(kc, "cpu_info", lookup_instance, NULL)){
163+
cpuinfo = Object::New();
164+
165+
if (kstat_read(kc, ksp, NULL) == -1) {
166+
/*
167+
* It is deeply annoying, but some kstats can return errors
168+
* under otherwise routine conditions. (ACPI is one
169+
* offender; there are surely others.) To prevent these
170+
* fouled kstats from completely ruining our day, we assign
171+
* an "error" member to the return value that consists of
172+
* the strerror().
173+
*/
174+
cpuinfo->Set(String::New("error"), String::New(strerror(errno)));
175+
(*cpus)->Set(lookup_instance, cpuinfo);
176+
} else {
177+
knp = (kstat_named_t *) kstat_data_lookup(ksp, "clock_MHz");
178+
cpuinfo->Set(String::New("speed"), data_named(knp));
179+
knp = (kstat_named_t *) kstat_data_lookup(ksp, "brand");
180+
cpuinfo->Set(String::New("model"), data_named(knp));
181+
(*cpus)->Set(lookup_instance, cpuinfo);
182+
}
183+
184+
lookup_instance++;
185+
}
186+
187+
lookup_instance = 0;
188+
while (ksp = kstat_lookup(kc, "cpu", lookup_instance, "sys")){
189+
cpuinfo = (*cpus)->Get(lookup_instance)->ToObject();
190+
cputimes = Object::New();
191+
192+
if (kstat_read(kc, ksp, NULL) == -1) {
193+
cputimes->Set(String::New("error"), String::New(strerror(errno)));
194+
cpuinfo->Set(String::New("times"), cpuinfo);
195+
} else {
196+
knp = (kstat_named_t *) kstat_data_lookup(ksp, "cpu_ticks_kernel");
197+
cputimes->Set(String::New("system"), data_named(knp));
198+
knp = (kstat_named_t *) kstat_data_lookup(ksp, "cpu_ticks_user");
199+
cputimes->Set(String::New("user"), data_named(knp));
200+
knp = (kstat_named_t *) kstat_data_lookup(ksp, "cpu_ticks_idle");
201+
cputimes->Set(String::New("idle"), data_named(knp));
202+
knp = (kstat_named_t *) kstat_data_lookup(ksp, "intr");
203+
cputimes->Set(String::New("irq"), data_named(knp));
204+
205+
cpuinfo->Set(String::New("times"), cputimes);
206+
}
207+
208+
lookup_instance++;
209+
}
210+
211+
kstat_close(kc);
212+
116213
return 0;
117214
}
118215

@@ -126,12 +223,30 @@ double Platform::GetTotalMemory() {
126223
return 0.0;
127224
}
128225

129-
130226
double Platform::GetUptime() {
131-
// http://munin-monitoring.org/attachment/ticket/419/uptime
132-
return 0.0;
133-
}
227+
kstat_ctl_t *kc;
228+
kstat_t *ksp;
229+
kstat_named_t *knp;
230+
231+
long hz = sysconf(_SC_CLK_TCK);
232+
ulong_t clk_intr;
233+
234+
if ((kc = kstat_open()) == NULL)
235+
throw "could not open kstat";
236+
237+
ksp = kstat_lookup(kc, "unix", 0, "system_misc");
134238

239+
if (kstat_read(kc, ksp, NULL) == -1) {
240+
throw "unable to read kstat";
241+
} else {
242+
knp = (kstat_named_t *) kstat_data_lookup(ksp, "clk_intr");
243+
clk_intr = knp->value.ul;
244+
}
245+
246+
kstat_close(kc);
247+
248+
return static_cast<double>( clk_intr / hz );
249+
}
135250

136251
int Platform::GetLoadAvg(Local<Array> *loads) {
137252
return 0;

test/simple/test-os.js

+26-8
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,29 @@ var common = require('../common');
2323
var assert = require('assert');
2424
var os = require('os');
2525

26-
assert.ok(os.hostname().length > 0);
27-
assert.ok(os.loadavg().length > 0);
28-
assert.ok(os.uptime() > 0);
29-
assert.ok(os.freemem() > 0);
30-
assert.ok(os.totalmem() > 0);
31-
assert.ok(os.cpus().length > 0);
32-
assert.ok(os.type().length > 0);
33-
assert.ok(os.release().length > 0);
26+
var hostname = os.hostname()
27+
console.log("hostname = %s", hostname);
28+
assert.ok(hostname.length > 0);
29+
30+
var uptime = os.uptime();
31+
console.log("uptime = %d", uptime);
32+
assert.ok(uptime > 0);
33+
34+
var cpus = os.cpus();
35+
console.log("cpus = ", cpus);
36+
assert.ok(cpus.length > 0);
37+
38+
var type = os.type();
39+
console.log("type = ", type);
40+
assert.ok(type.length > 0);
41+
42+
var release = os.release();
43+
console.log("release = ", release);
44+
assert.ok(release.length > 0);
45+
46+
if (process.platform != 'sunos') {
47+
// not implemeneted yet
48+
assert.ok(os.loadavg().length > 0);
49+
assert.ok(os.freemem() > 0);
50+
assert.ok(os.totalmem() > 0);
51+
}

wscript

+3-1
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,8 @@ def configure(conf):
359359
conf.fatal("Cannot find socket library")
360360
if not conf.check(lib='nsl', uselib_store="NSL"):
361361
conf.fatal("Cannot find nsl library")
362+
if not conf.check(lib='kstat', uselib_store="KSTAT"):
363+
conf.fatal("Cannot find kstat library")
362364

363365
conf.sub_config('deps/libeio')
364366

@@ -802,7 +804,7 @@ def build(bld):
802804
node = bld.new_task_gen("cxx", product_type)
803805
node.name = "node"
804806
node.target = "node"
805-
node.uselib = 'RT EV OPENSSL CARES EXECINFO DL KVM SOCKET NSL UTIL OPROFILE'
807+
node.uselib = 'RT EV OPENSSL CARES EXECINFO DL KVM SOCKET NSL KSTAT UTIL OPROFILE'
806808
node.add_objects = 'eio http_parser'
807809
if product_type_is_lib:
808810
node.install_path = '${LIBDIR}'

0 commit comments

Comments
 (0)