Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/os/solaris/vm/os_perf_solaris.cpp
32285 views
1
/*
2
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*
23
*/
24
25
#include "precompiled.hpp"
26
#include "jvm.h"
27
#include "memory/allocation.inline.hpp"
28
#include "runtime/os.hpp"
29
#include "runtime/os_perf.hpp"
30
#include "os_solaris.inline.hpp"
31
#include "utilities/macros.hpp"
32
33
#ifdef TARGET_ARCH_aarch32
34
# include "vm_version_ext_aarch32.hpp"
35
#endif
36
#ifdef TARGET_ARCH_x86
37
# include "vm_version_ext_x86.hpp"
38
#endif
39
#ifdef TARGET_ARCH_sparc
40
# include "vm_version_ext_sparc.hpp"
41
#endif
42
#ifdef TARGET_ARCH_zero
43
# include "vm_version_ext_zero.hpp"
44
#endif
45
#ifdef TARGET_ARCH_arm
46
# include "vm_version_ext_arm.hpp"
47
#endif
48
#ifdef TARGET_ARCH_ppc
49
# include "vm_version_ext_ppc.hpp"
50
#endif
51
52
#include <sys/types.h>
53
#include <procfs.h>
54
#include <dirent.h>
55
#include <errno.h>
56
#include <stdio.h>
57
#include <stdlib.h>
58
#include <strings.h>
59
#include <unistd.h>
60
#include <fcntl.h>
61
#include <kstat.h>
62
#include <unistd.h>
63
#include <string.h>
64
#include <sys/sysinfo.h>
65
#include <sys/lwp.h>
66
#include <pthread.h>
67
#include <time.h>
68
#include <utmpx.h>
69
#include <dlfcn.h>
70
#include <sys/loadavg.h>
71
#include <limits.h>
72
73
static const double NANOS_PER_SEC = 1000000000.0;
74
75
struct CPUPerfTicks {
76
kstat_t* kstat;
77
uint64_t last_idle;
78
uint64_t last_total;
79
double last_ratio;
80
};
81
82
struct CPUPerfCounters {
83
int nProcs;
84
CPUPerfTicks* jvmTicks;
85
kstat_ctl_t* kstat_ctrl;
86
};
87
88
static int get_info(const char* path, void* info, size_t s, off_t o) {
89
assert(path != NULL, "path is NULL!");
90
assert(info != NULL, "info is NULL!");
91
92
int fd = -1;
93
94
if ((fd = open(path, O_RDONLY)) < 0) {
95
return OS_ERR;
96
}
97
if (pread(fd, info, s, o) != s) {
98
close(fd);
99
return OS_ERR;
100
}
101
close(fd);
102
return OS_OK;
103
}
104
105
static int get_psinfo2(void* info, size_t s, off_t o) {
106
return get_info("/proc/self/psinfo", info, s, o);
107
}
108
109
static int get_psinfo(psinfo_t* info) {
110
return get_psinfo2(info, sizeof(*info), 0);
111
}
112
113
static int get_psinfo(char* file, psinfo_t* info) {
114
assert(file != NULL, "file is NULL!");
115
assert(info != NULL, "info is NULL!");
116
return get_info(file, info, sizeof(*info), 0);
117
}
118
119
120
static int get_usage(prusage_t* usage) {
121
assert(usage != NULL, "usage is NULL!");
122
return get_info("/proc/self/usage", usage, sizeof(*usage), 0);
123
}
124
125
static int read_cpustat(kstat_ctl_t* kstat_ctrl, CPUPerfTicks* load, cpu_stat_t* cpu_stat) {
126
assert(kstat_ctrl != NULL, "kstat_ctrl pointer is NULL!");
127
assert(load != NULL, "load pointer is NULL!");
128
assert(cpu_stat != NULL, "cpu_stat pointer is NULL!");
129
130
if (load->kstat == NULL) {
131
// no handle.
132
return OS_ERR;
133
}
134
if (kstat_read(kstat_ctrl, load->kstat, cpu_stat) == OS_ERR) {
135
// disable handle for this CPU
136
load->kstat = NULL;
137
return OS_ERR;
138
}
139
return OS_OK;
140
}
141
142
static double get_cpu_load(int which_logical_cpu, CPUPerfCounters* counters) {
143
assert(counters != NULL, "counters pointer is NULL!");
144
145
cpu_stat_t cpu_stat = {0};
146
147
if (which_logical_cpu >= counters->nProcs) {
148
return .0;
149
}
150
151
CPUPerfTicks load = counters->jvmTicks[which_logical_cpu];
152
if (read_cpustat(counters->kstat_ctrl, &load, &cpu_stat) != OS_OK) {
153
return .0;
154
}
155
156
uint_t* usage = cpu_stat.cpu_sysinfo.cpu;
157
if (usage == NULL) {
158
return .0;
159
}
160
161
uint64_t c_idle = usage[CPU_IDLE];
162
uint64_t c_total = 0;
163
164
for (int i = 0; i < CPU_STATES; i++) {
165
c_total += usage[i];
166
}
167
168
// Calculate diff against previous snapshot
169
uint64_t d_idle = c_idle - load.last_idle;
170
uint64_t d_total = c_total - load.last_total;
171
172
/** update if weve moved */
173
if (d_total > 0) {
174
// Save current values for next time around
175
load.last_idle = c_idle;
176
load.last_total = c_total;
177
load.last_ratio = (double) (d_total - d_idle) / d_total;
178
}
179
180
return load.last_ratio;
181
}
182
183
static int get_boot_time(uint64_t* time) {
184
assert(time != NULL, "time pointer is NULL!");
185
setutxent();
186
for(;;) {
187
struct utmpx* u;
188
if ((u = getutxent()) == NULL) {
189
break;
190
}
191
if (u->ut_type == BOOT_TIME) {
192
*time = u->ut_xtime;
193
endutxent();
194
return OS_OK;
195
}
196
}
197
endutxent();
198
return OS_ERR;
199
}
200
201
static int get_noof_context_switches(CPUPerfCounters* counters, uint64_t* switches) {
202
assert(switches != NULL, "switches pointer is NULL!");
203
assert(counters != NULL, "counter pointer is NULL!");
204
*switches = 0;
205
uint64_t s = 0;
206
207
// Collect data from all CPUs
208
for (int i = 0; i < counters->nProcs; i++) {
209
cpu_stat_t cpu_stat = {0};
210
CPUPerfTicks load = counters->jvmTicks[i];
211
212
if (read_cpustat(counters->kstat_ctrl, &load, &cpu_stat) == OS_OK) {
213
s += cpu_stat.cpu_sysinfo.pswitch;
214
} else {
215
//fail fast...
216
return OS_ERR;
217
}
218
}
219
*switches = s;
220
return OS_OK;
221
}
222
223
static int perf_context_switch_rate(CPUPerfCounters* counters, double* rate) {
224
assert(counters != NULL, "counters is NULL!");
225
assert(rate != NULL, "rate pointer is NULL!");
226
static pthread_mutex_t contextSwitchLock = PTHREAD_MUTEX_INITIALIZER;
227
static uint64_t lastTime = 0;
228
static uint64_t lastSwitches = 0;
229
static double lastRate = 0.0;
230
231
uint64_t lt = 0;
232
int res = 0;
233
234
if (lastTime == 0) {
235
uint64_t tmp;
236
if (get_boot_time(&tmp) < 0) {
237
return OS_ERR;
238
}
239
lt = tmp * 1000;
240
}
241
242
res = OS_OK;
243
244
pthread_mutex_lock(&contextSwitchLock);
245
{
246
247
uint64_t sw = 0;
248
clock_t t, d;
249
250
if (lastTime == 0) {
251
lastTime = lt;
252
}
253
254
t = clock();
255
d = t - lastTime;
256
257
if (d == 0) {
258
*rate = lastRate;
259
} else if (get_noof_context_switches(counters, &sw)== OS_OK) {
260
*rate = ((double)(sw - lastSwitches) / d) * 1000;
261
lastRate = *rate;
262
lastSwitches = sw;
263
lastTime = t;
264
} else {
265
*rate = 0.0;
266
res = OS_ERR;
267
}
268
if (*rate < 0.0) {
269
*rate = 0.0;
270
lastRate = 0.0;
271
}
272
}
273
pthread_mutex_unlock(&contextSwitchLock);
274
return res;
275
}
276
277
278
279
class CPUPerformanceInterface::CPUPerformance : public CHeapObj<mtInternal> {
280
friend class CPUPerformanceInterface;
281
private:
282
CPUPerfCounters _counters;
283
int cpu_load(int which_logical_cpu, double* cpu_load);
284
int context_switch_rate(double* rate);
285
int cpu_load_total_process(double* cpu_load);
286
int cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad);
287
288
CPUPerformance();
289
~CPUPerformance();
290
bool initialize();
291
};
292
293
CPUPerformanceInterface::CPUPerformance::CPUPerformance() {
294
_counters.nProcs = 0;
295
_counters.jvmTicks = NULL;
296
_counters.kstat_ctrl = NULL;
297
}
298
299
bool CPUPerformanceInterface::CPUPerformance::initialize() {
300
// initialize kstat control structure,
301
_counters.kstat_ctrl = kstat_open();
302
assert(_counters.kstat_ctrl != NULL, "error initializing kstat control structure!");
303
304
if (NULL == _counters.kstat_ctrl) {
305
return false;
306
}
307
308
// Get number of CPU(s)
309
if ((_counters.nProcs = sysconf(_SC_NPROCESSORS_ONLN)) == OS_ERR) {
310
// ignore error?
311
_counters.nProcs = 1;
312
}
313
314
assert(_counters.nProcs > 0, "no CPUs detected in sysconf call!");
315
if (_counters.nProcs == 0) {
316
return false;
317
}
318
319
// Data structure(s) for saving CPU load (one per CPU)
320
size_t tick_array_size = _counters.nProcs * sizeof(CPUPerfTicks);
321
_counters.jvmTicks = (CPUPerfTicks*)NEW_C_HEAP_ARRAY(char, tick_array_size, mtInternal);
322
if (NULL == _counters.jvmTicks) {
323
return false;
324
}
325
memset(_counters.jvmTicks, 0, tick_array_size);
326
327
// Get kstat cpu_stat counters for every CPU
328
// loop over kstat to find our cpu_stat(s)
329
int i = 0;
330
for (kstat_t* kstat = _counters.kstat_ctrl->kc_chain; kstat != NULL; kstat = kstat->ks_next) {
331
if (strncmp(kstat->ks_module, "cpu_stat", 8) == 0) {
332
if (kstat_read(_counters.kstat_ctrl, kstat, NULL) == OS_ERR) {
333
continue;
334
}
335
if (i == _counters.nProcs) {
336
// more cpu_stats than reported CPUs
337
break;
338
}
339
_counters.jvmTicks[i++].kstat = kstat;
340
}
341
}
342
return true;
343
}
344
345
CPUPerformanceInterface::CPUPerformance::~CPUPerformance() {
346
if (_counters.jvmTicks != NULL) {
347
FREE_C_HEAP_ARRAY(char, _counters.jvmTicks, mtInternal);
348
}
349
if (_counters.kstat_ctrl != NULL) {
350
kstat_close(_counters.kstat_ctrl);
351
}
352
}
353
354
int CPUPerformanceInterface::CPUPerformance::cpu_load(int which_logical_cpu, double* cpu_load) {
355
assert(cpu_load != NULL, "cpu_load pointer is NULL!");
356
double t = .0;
357
if (-1 == which_logical_cpu) {
358
for (int i = 0; i < _counters.nProcs; i++) {
359
t += get_cpu_load(i, &_counters);
360
}
361
// Cap total systemload to 1.0
362
t = MIN2<double>((t / _counters.nProcs), 1.0);
363
} else {
364
t = MIN2<double>(get_cpu_load(which_logical_cpu, &_counters), 1.0);
365
}
366
367
*cpu_load = t;
368
return OS_OK;
369
}
370
371
int CPUPerformanceInterface::CPUPerformance::cpu_load_total_process(double* cpu_load) {
372
assert(cpu_load != NULL, "cpu_load pointer is NULL!");
373
374
psinfo_t info;
375
376
// Get the percentage of "recent cpu usage" from all the lwp:s in the JVM:s
377
// process. This is returned as a value between 0.0 and 1.0 multiplied by 0x8000.
378
if (get_psinfo2(&info.pr_pctcpu, sizeof(info.pr_pctcpu), offsetof(psinfo_t, pr_pctcpu)) != 0) {
379
*cpu_load = 0.0;
380
return OS_ERR;
381
}
382
*cpu_load = (double) info.pr_pctcpu / 0x8000;
383
return OS_OK;
384
}
385
386
int CPUPerformanceInterface::CPUPerformance::cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad) {
387
assert(pjvmUserLoad != NULL, "pjvmUserLoad not inited");
388
assert(pjvmKernelLoad != NULL, "pjvmKernelLoad not inited");
389
assert(psystemTotalLoad != NULL, "psystemTotalLoad not inited");
390
391
static uint64_t lastTime;
392
static uint64_t lastUser, lastKernel;
393
static double lastUserRes, lastKernelRes;
394
395
pstatus_t pss;
396
psinfo_t info;
397
398
*pjvmKernelLoad = *pjvmUserLoad = *psystemTotalLoad = 0;
399
if (get_info("/proc/self/status", &pss.pr_utime, sizeof(timestruc_t)*2, offsetof(pstatus_t, pr_utime)) != 0) {
400
return OS_ERR;
401
}
402
403
if (get_psinfo(&info) != 0) {
404
return OS_ERR;
405
}
406
407
// get the total time in user, kernel and total time
408
// check ratios for 'lately' and multiply the 'recent load'.
409
uint64_t time = (info.pr_time.tv_sec * NANOS_PER_SEC) + info.pr_time.tv_nsec;
410
uint64_t user = (pss.pr_utime.tv_sec * NANOS_PER_SEC) + pss.pr_utime.tv_nsec;
411
uint64_t kernel = (pss.pr_stime.tv_sec * NANOS_PER_SEC) + pss.pr_stime.tv_nsec;
412
uint64_t diff = time - lastTime;
413
double load = (double) info.pr_pctcpu / 0x8000;
414
415
if (diff > 0) {
416
lastUserRes = (load * (user - lastUser)) / diff;
417
lastKernelRes = (load * (kernel - lastKernel)) / diff;
418
419
// BUG9182835 - patch for clamping these values to sane ones.
420
lastUserRes = MIN2<double>(1, lastUserRes);
421
lastUserRes = MAX2<double>(0, lastUserRes);
422
lastKernelRes = MIN2<double>(1, lastKernelRes);
423
lastKernelRes = MAX2<double>(0, lastKernelRes);
424
}
425
426
double t = .0;
427
cpu_load(-1, &t);
428
// clamp at user+system and 1.0
429
if (lastUserRes + lastKernelRes > t) {
430
t = MIN2<double>(lastUserRes + lastKernelRes, 1.0);
431
}
432
433
*pjvmUserLoad = lastUserRes;
434
*pjvmKernelLoad = lastKernelRes;
435
*psystemTotalLoad = t;
436
437
lastTime = time;
438
lastUser = user;
439
lastKernel = kernel;
440
441
return OS_OK;
442
}
443
444
int CPUPerformanceInterface::CPUPerformance::context_switch_rate(double* rate) {
445
return perf_context_switch_rate(&_counters, rate);
446
}
447
448
CPUPerformanceInterface::CPUPerformanceInterface() {
449
_impl = NULL;
450
}
451
452
bool CPUPerformanceInterface::initialize() {
453
_impl = new CPUPerformanceInterface::CPUPerformance();
454
return _impl != NULL && _impl->initialize();
455
}
456
457
CPUPerformanceInterface::~CPUPerformanceInterface(void) {
458
if (_impl != NULL) {
459
delete _impl;
460
}
461
}
462
463
int CPUPerformanceInterface::cpu_load(int which_logical_cpu, double* const cpu_load) const {
464
return _impl->cpu_load(which_logical_cpu, cpu_load);
465
}
466
467
int CPUPerformanceInterface::cpu_load_total_process(double* const cpu_load) const {
468
return _impl->cpu_load_total_process(cpu_load);
469
}
470
471
int CPUPerformanceInterface::cpu_loads_process(double* const pjvmUserLoad, double* const pjvmKernelLoad, double* const psystemTotalLoad) const {
472
return _impl->cpu_loads_process(pjvmUserLoad, pjvmKernelLoad, psystemTotalLoad);
473
}
474
475
int CPUPerformanceInterface::context_switch_rate(double* const rate) const {
476
return _impl->context_switch_rate(rate);
477
}
478
479
class SystemProcessInterface::SystemProcesses : public CHeapObj<mtInternal> {
480
friend class SystemProcessInterface;
481
private:
482
class ProcessIterator : public CHeapObj<mtInternal> {
483
friend class SystemProcessInterface::SystemProcesses;
484
private:
485
DIR* _dir;
486
struct dirent* _entry;
487
bool _valid;
488
489
ProcessIterator();
490
~ProcessIterator();
491
bool initialize();
492
493
bool is_valid() const { return _valid; }
494
bool is_valid_entry(struct dirent* const entry) const;
495
bool is_dir(const char* const name) const;
496
char* allocate_string(const char* const str) const;
497
int current(SystemProcess* const process_info);
498
int next_process();
499
};
500
501
ProcessIterator* _iterator;
502
SystemProcesses();
503
bool initialize();
504
~SystemProcesses();
505
506
//information about system processes
507
int system_processes(SystemProcess** system_processes, int* no_of_sys_processes) const;
508
};
509
510
bool SystemProcessInterface::SystemProcesses::ProcessIterator::is_dir(const char* name) const {
511
struct stat64 mystat;
512
int ret_val = 0;
513
514
ret_val = ::stat64(name, &mystat);
515
516
if (ret_val < 0) {
517
return false;
518
}
519
ret_val = S_ISDIR(mystat.st_mode);
520
return ret_val > 0;
521
}
522
523
// if it has a numeric name, is a directory and has a 'psinfo' file in it
524
bool SystemProcessInterface::SystemProcesses::ProcessIterator::is_valid_entry(struct dirent* entry) const {
525
// ignore the "." and ".." directories
526
if ((strcmp(entry->d_name, ".") == 0) ||
527
(strcmp(entry->d_name, "..") == 0)) {
528
return false;
529
}
530
531
char buffer[PATH_MAX] = {0};
532
uint64_t size = 0;
533
bool result = false;
534
FILE *fp = NULL;
535
536
if (atoi(entry->d_name) != 0) {
537
jio_snprintf(buffer, PATH_MAX, "/proc/%s", entry->d_name);
538
539
if (is_dir(buffer)) {
540
memset(buffer, 0, PATH_MAX);
541
jio_snprintf(buffer, PATH_MAX, "/proc/%s/psinfo", entry->d_name);
542
if ((fp = fopen(buffer, "r")) != NULL) {
543
int nread = 0;
544
psinfo_t psinfo_data;
545
if ((nread = fread(&psinfo_data, 1, sizeof(psinfo_t), fp)) != -1) {
546
// only considering system process owned by root
547
if (psinfo_data.pr_uid == 0) {
548
result = true;
549
}
550
}
551
}
552
}
553
}
554
555
if (fp != NULL) {
556
fclose(fp);
557
}
558
559
return result;
560
}
561
562
char* SystemProcessInterface::SystemProcesses::ProcessIterator::allocate_string(const char* str) const {
563
if (str != NULL) {
564
size_t len = strlen(str);
565
char* tmp = NEW_C_HEAP_ARRAY(char, len+1, mtInternal);
566
strncpy(tmp, str, len);
567
tmp[len] = '\0';
568
return tmp;
569
}
570
return NULL;
571
}
572
573
int SystemProcessInterface::SystemProcesses::ProcessIterator::current(SystemProcess* process_info) {
574
if (!is_valid()) {
575
return OS_ERR;
576
}
577
578
char psinfo_path[PATH_MAX] = {0};
579
jio_snprintf(psinfo_path, PATH_MAX, "/proc/%s/psinfo", _entry->d_name);
580
581
FILE *fp = NULL;
582
if ((fp = fopen(psinfo_path, "r")) == NULL) {
583
return OS_ERR;
584
}
585
586
int nread = 0;
587
psinfo_t psinfo_data;
588
if ((nread = fread(&psinfo_data, 1, sizeof(psinfo_t), fp)) == -1) {
589
fclose(fp);
590
return OS_ERR;
591
}
592
593
char *exe_path = NULL;
594
if ((psinfo_data.pr_fname != NULL) &&
595
(psinfo_data.pr_psargs != NULL)) {
596
char *path_substring = strstr(psinfo_data.pr_psargs, psinfo_data.pr_fname);
597
if (path_substring != NULL) {
598
int len = path_substring - psinfo_data.pr_psargs;
599
exe_path = NEW_C_HEAP_ARRAY(char, len+1, mtInternal);
600
if (exe_path != NULL) {
601
jio_snprintf(exe_path, len, "%s", psinfo_data.pr_psargs);
602
exe_path[len] = '\0';
603
}
604
}
605
}
606
607
process_info->set_pid(atoi(_entry->d_name));
608
process_info->set_name(allocate_string(psinfo_data.pr_fname));
609
process_info->set_path(allocate_string(exe_path));
610
process_info->set_command_line(allocate_string(psinfo_data.pr_psargs));
611
612
if (exe_path != NULL) {
613
FREE_C_HEAP_ARRAY(char, exe_path, mtInternal);
614
}
615
616
if (fp != NULL) {
617
fclose(fp);
618
}
619
620
return OS_OK;
621
}
622
623
int SystemProcessInterface::SystemProcesses::ProcessIterator::next_process() {
624
if (!is_valid()) {
625
return OS_ERR;
626
}
627
628
do {
629
_entry = os::readdir(_dir);
630
if (_entry == NULL) {
631
// Error or reached end. Could use errno to distinguish those cases.
632
_valid = false;
633
return OS_ERR;
634
}
635
} while(!is_valid_entry(_entry));
636
637
_valid = true;
638
return OS_OK;
639
}
640
641
SystemProcessInterface::SystemProcesses::ProcessIterator::ProcessIterator() {
642
_dir = NULL;
643
_entry = NULL;
644
_valid = false;
645
}
646
647
bool SystemProcessInterface::SystemProcesses::ProcessIterator::initialize() {
648
_dir = os::opendir("/proc");
649
_entry = NULL;
650
_valid = true;
651
next_process();
652
653
return true;
654
}
655
656
SystemProcessInterface::SystemProcesses::ProcessIterator::~ProcessIterator() {
657
if (_dir != NULL) {
658
os::closedir(_dir);
659
}
660
}
661
662
SystemProcessInterface::SystemProcesses::SystemProcesses() {
663
_iterator = NULL;
664
}
665
666
bool SystemProcessInterface::SystemProcesses::initialize() {
667
_iterator = new SystemProcessInterface::SystemProcesses::ProcessIterator();
668
return _iterator != NULL && _iterator->initialize();
669
}
670
671
SystemProcessInterface::SystemProcesses::~SystemProcesses() {
672
if (_iterator != NULL) {
673
delete _iterator;
674
}
675
}
676
677
int SystemProcessInterface::SystemProcesses::system_processes(SystemProcess** system_processes, int* no_of_sys_processes) const {
678
assert(system_processes != NULL, "system_processes pointer is NULL!");
679
assert(no_of_sys_processes != NULL, "system_processes counter pointer is NULL!");
680
assert(_iterator != NULL, "iterator is NULL!");
681
682
// initialize pointers
683
*no_of_sys_processes = 0;
684
*system_processes = NULL;
685
686
while (_iterator->is_valid()) {
687
SystemProcess* tmp = new SystemProcess();
688
_iterator->current(tmp);
689
690
//if already existing head
691
if (*system_processes != NULL) {
692
//move "first to second"
693
tmp->set_next(*system_processes);
694
}
695
// new head
696
*system_processes = tmp;
697
// increment
698
(*no_of_sys_processes)++;
699
// step forward
700
_iterator->next_process();
701
}
702
return OS_OK;
703
}
704
705
int SystemProcessInterface::system_processes(SystemProcess** system_procs, int* const no_of_sys_processes) const {
706
return _impl->system_processes(system_procs, no_of_sys_processes);
707
}
708
709
SystemProcessInterface::SystemProcessInterface() {
710
_impl = NULL;
711
}
712
713
bool SystemProcessInterface::initialize() {
714
_impl = new SystemProcessInterface::SystemProcesses();
715
return _impl != NULL && _impl->initialize();
716
717
}
718
719
SystemProcessInterface::~SystemProcessInterface() {
720
if (_impl != NULL) {
721
delete _impl;
722
}
723
}
724
725
CPUInformationInterface::CPUInformationInterface() {
726
_cpu_info = NULL;
727
}
728
729
bool CPUInformationInterface::initialize() {
730
_cpu_info = new CPUInformation();
731
if (_cpu_info == NULL) {
732
return false;
733
}
734
_cpu_info->set_number_of_hardware_threads(VM_Version_Ext::number_of_threads());
735
_cpu_info->set_number_of_cores(VM_Version_Ext::number_of_cores());
736
_cpu_info->set_number_of_sockets(VM_Version_Ext::number_of_sockets());
737
_cpu_info->set_cpu_name(VM_Version_Ext::cpu_name());
738
_cpu_info->set_cpu_description(VM_Version_Ext::cpu_description());
739
return true;
740
}
741
742
CPUInformationInterface::~CPUInformationInterface() {
743
if (_cpu_info != NULL) {
744
if (_cpu_info->cpu_name() != NULL) {
745
const char* cpu_name = _cpu_info->cpu_name();
746
FREE_C_HEAP_ARRAY(char, cpu_name, mtInternal);
747
_cpu_info->set_cpu_name(NULL);
748
}
749
if (_cpu_info->cpu_description() != NULL) {
750
const char* cpu_desc = _cpu_info->cpu_description();
751
FREE_C_HEAP_ARRAY(char, cpu_desc, mtInternal);
752
_cpu_info->set_cpu_description(NULL);
753
}
754
delete _cpu_info;
755
}
756
}
757
758
int CPUInformationInterface::cpu_information(CPUInformation& cpu_info) {
759
if (_cpu_info == NULL) {
760
return OS_ERR;
761
}
762
763
cpu_info = *_cpu_info; // shallow copy assignment
764
return OS_OK;
765
}
766
767
class NetworkPerformanceInterface::NetworkPerformance : public CHeapObj<mtInternal> {
768
friend class NetworkPerformanceInterface;
769
private:
770
NetworkPerformance();
771
NetworkPerformance(const NetworkPerformance& rhs); // no impl
772
NetworkPerformance& operator=(const NetworkPerformance& rhs); // no impl
773
bool initialize();
774
~NetworkPerformance();
775
int network_utilization(NetworkInterface** network_interfaces) const;
776
};
777
778
NetworkPerformanceInterface::NetworkPerformance::NetworkPerformance() {
779
780
}
781
782
bool NetworkPerformanceInterface::NetworkPerformance::initialize() {
783
return true;
784
}
785
786
NetworkPerformanceInterface::NetworkPerformance::~NetworkPerformance() {
787
788
}
789
790
int NetworkPerformanceInterface::NetworkPerformance::network_utilization(NetworkInterface** network_interfaces) const
791
{
792
kstat_ctl_t* ctl = kstat_open();
793
if (ctl == NULL) {
794
return OS_ERR;
795
}
796
797
NetworkInterface* ret = NULL;
798
for (kstat_t* k = ctl->kc_chain; k != NULL; k = k->ks_next) {
799
if (strcmp(k->ks_class, "net") != 0) {
800
continue;
801
}
802
if (strcmp(k->ks_module, "link") != 0) {
803
continue;
804
}
805
806
if (kstat_read(ctl, k, NULL) == -1) {
807
return OS_ERR;
808
}
809
810
uint64_t bytes_in = UINT64_MAX;
811
uint64_t bytes_out = UINT64_MAX;
812
for (int i = 0; i < k->ks_ndata; ++i) {
813
kstat_named_t* data = &reinterpret_cast<kstat_named_t*>(k->ks_data)[i];
814
if (strcmp(data->name, "rbytes64") == 0) {
815
bytes_in = data->value.ui64;
816
}
817
else if (strcmp(data->name, "obytes64") == 0) {
818
bytes_out = data->value.ui64;
819
}
820
}
821
822
if ((bytes_in != UINT64_MAX) && (bytes_out != UINT64_MAX)) {
823
NetworkInterface* cur = new NetworkInterface(k->ks_name, bytes_in, bytes_out, ret);
824
ret = cur;
825
}
826
}
827
828
kstat_close(ctl);
829
*network_interfaces = ret;
830
831
return OS_OK;
832
}
833
834
NetworkPerformanceInterface::NetworkPerformanceInterface() {
835
_impl = NULL;
836
}
837
838
NetworkPerformanceInterface::~NetworkPerformanceInterface() {
839
if (_impl != NULL) {
840
delete _impl;
841
}
842
}
843
844
bool NetworkPerformanceInterface::initialize() {
845
_impl = new NetworkPerformanceInterface::NetworkPerformance();
846
return _impl != NULL && _impl->initialize();
847
}
848
849
int NetworkPerformanceInterface::network_utilization(NetworkInterface** network_interfaces) const {
850
return _impl->network_utilization(network_interfaces);
851
}
852
853