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
4751using namespace v8 ;
4852
53+
4954char ** 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
114146int 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-
130226double 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
136251int Platform::GetLoadAvg (Local<Array> *loads) {
137252 return 0 ;
0 commit comments