Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-aarch32-jdk8u
Path: blob/jdk8u272-b10-aarch32-20201026/hotspot/src/os/linux/vm/os_perf_linux.cpp
48785 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 "os_linux.inline.hpp"
29
#include "runtime/os.hpp"
30
#include "runtime/os_perf.hpp"
31
32
#ifdef TARGET_ARCH_aarch32
33
# include "vm_version_ext_aarch32.hpp"
34
#endif
35
#ifdef TARGET_ARCH_aarch64
36
# include "vm_version_ext_aarch64.hpp"
37
#endif
38
#ifdef TARGET_ARCH_x86
39
# include "vm_version_ext_x86.hpp"
40
#endif
41
#ifdef TARGET_ARCH_sparc
42
# include "vm_version_ext_sparc.hpp"
43
#endif
44
#ifdef TARGET_ARCH_zero
45
# include "vm_version_ext_zero.hpp"
46
#endif
47
#ifdef TARGET_ARCH_arm
48
# include "vm_version_ext_arm.hpp"
49
#endif
50
#ifdef TARGET_ARCH_ppc
51
# include "vm_version_ext_ppc.hpp"
52
#endif
53
54
#include <stdio.h>
55
#include <stdarg.h>
56
#include <unistd.h>
57
#include <errno.h>
58
#include <string.h>
59
#include <sys/resource.h>
60
#include <sys/types.h>
61
#include <sys/stat.h>
62
#include <dirent.h>
63
#include <stdlib.h>
64
#include <dlfcn.h>
65
#include <pthread.h>
66
#include <limits.h>
67
#ifdef __ANDROID__
68
# include "ifaddrs.h"
69
#else
70
# include <ifaddrs.h>
71
#endif
72
#include <fcntl.h>
73
74
/**
75
/proc/[number]/stat
76
Status information about the process. This is used by ps(1). It is defined in /usr/src/linux/fs/proc/array.c.
77
78
The fields, in order, with their proper scanf(3) format specifiers, are:
79
80
1. pid %d The process id.
81
82
2. comm %s
83
The filename of the executable, in parentheses. This is visible whether or not the executable is swapped out.
84
85
3. state %c
86
One character from the string "RSDZTW" where R is running, S is sleeping in an interruptible wait, D is waiting in uninterruptible disk
87
sleep, Z is zombie, T is traced or stopped (on a signal), and W is paging.
88
89
4. ppid %d
90
The PID of the parent.
91
92
5. pgrp %d
93
The process group ID of the process.
94
95
6. session %d
96
The session ID of the process.
97
98
7. tty_nr %d
99
The tty the process uses.
100
101
8. tpgid %d
102
The process group ID of the process which currently owns the tty that the process is connected to.
103
104
9. flags %lu
105
The flags of the process. The math bit is decimal 4, and the traced bit is decimal 10.
106
107
10. minflt %lu
108
The number of minor faults the process has made which have not required loading a memory page from disk.
109
110
11. cminflt %lu
111
The number of minor faults that the process's waited-for children have made.
112
113
12. majflt %lu
114
The number of major faults the process has made which have required loading a memory page from disk.
115
116
13. cmajflt %lu
117
The number of major faults that the process's waited-for children have made.
118
119
14. utime %lu
120
The number of jiffies that this process has been scheduled in user mode.
121
122
15. stime %lu
123
The number of jiffies that this process has been scheduled in kernel mode.
124
125
16. cutime %ld
126
The number of jiffies that this process's waited-for children have been scheduled in user mode. (See also times(2).)
127
128
17. cstime %ld
129
The number of jiffies that this process' waited-for children have been scheduled in kernel mode.
130
131
18. priority %ld
132
The standard nice value, plus fifteen. The value is never negative in the kernel.
133
134
19. nice %ld
135
The nice value ranges from 19 (nicest) to -19 (not nice to others).
136
137
20. 0 %ld This value is hard coded to 0 as a placeholder for a removed field.
138
139
21. itrealvalue %ld
140
The time in jiffies before the next SIGALRM is sent to the process due to an interval timer.
141
142
22. starttime %lu
143
The time in jiffies the process started after system boot.
144
145
23. vsize %lu
146
Virtual memory size in bytes.
147
148
24. rss %ld
149
Resident Set Size: number of pages the process has in real memory, minus 3 for administrative purposes. This is just the pages which count
150
towards text, data, or stack space. This does not include pages which have not been demand-loaded in, or which are swapped out.
151
152
25. rlim %lu
153
Current limit in bytes on the rss of the process (usually 4294967295 on i386).
154
155
26. startcode %lu
156
The address above which program text can run.
157
158
27. endcode %lu
159
The address below which program text can run.
160
161
28. startstack %lu
162
The address of the start of the stack.
163
164
29. kstkesp %lu
165
The current value of esp (stack pointer), as found in the kernel stack page for the process.
166
167
30. kstkeip %lu
168
The current EIP (instruction pointer).
169
170
31. signal %lu
171
The bitmap of pending signals (usually 0).
172
173
32. blocked %lu
174
The bitmap of blocked signals (usually 0, 2 for shells).
175
176
33. sigignore %lu
177
The bitmap of ignored signals.
178
179
34. sigcatch %lu
180
The bitmap of catched signals.
181
182
35. wchan %lu
183
This is the "channel" in which the process is waiting. It is the address of a system call, and can be looked up in a namelist if you need
184
a textual name. (If you have an up-to-date /etc/psdatabase, then try ps -l to see the WCHAN field in action.)
185
186
36. nswap %lu
187
Number of pages swapped - not maintained.
188
189
37. cnswap %lu
190
Cumulative nswap for child processes.
191
192
38. exit_signal %d
193
Signal to be sent to parent when we die.
194
195
39. processor %d
196
CPU number last executed on.
197
198
199
200
///// SSCANF FORMAT STRING. Copy and use.
201
202
field: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
203
format: %d %s %c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %d %d
204
205
206
*/
207
208
/**
209
* For platforms that have them, when declaring
210
* a printf-style function,
211
* formatSpec is the parameter number (starting at 1)
212
* that is the format argument ("%d pid %s")
213
* params is the parameter number where the actual args to
214
* the format starts. If the args are in a va_list, this
215
* should be 0.
216
*/
217
#ifndef PRINTF_ARGS
218
# define PRINTF_ARGS(formatSpec, params) ATTRIBUTE_PRINTF(formatSpec, params)
219
#endif
220
221
#ifndef SCANF_ARGS
222
# define SCANF_ARGS(formatSpec, params) ATTRIBUTE_SCANF(formatSpec, params)
223
#endif
224
225
#ifndef _PRINTFMT_
226
# define _PRINTFMT_
227
#endif
228
229
#ifndef _SCANFMT_
230
# define _SCANFMT_
231
#endif
232
233
234
struct CPUPerfTicks {
235
uint64_t used;
236
uint64_t usedKernel;
237
uint64_t total;
238
};
239
240
typedef enum {
241
CPU_LOAD_VM_ONLY,
242
CPU_LOAD_GLOBAL,
243
} CpuLoadTarget;
244
245
enum {
246
UNDETECTED,
247
UNDETECTABLE,
248
LINUX26_NPTL,
249
BAREMETAL
250
};
251
252
struct CPUPerfCounters {
253
int nProcs;
254
CPUPerfTicks jvmTicks;
255
CPUPerfTicks* cpus;
256
};
257
258
static double get_cpu_load(int which_logical_cpu, CPUPerfCounters* counters, double* pkernelLoad, CpuLoadTarget target);
259
260
/** reads /proc/<pid>/stat data, with some checks and some skips.
261
* Ensure that 'fmt' does _NOT_ contain the first two "%d %s"
262
*/
263
static int SCANF_ARGS(2, 0) vread_statdata(const char* procfile, _SCANFMT_ const char* fmt, va_list args) {
264
FILE*f;
265
int n;
266
char buf[2048];
267
268
if ((f = fopen(procfile, "r")) == NULL) {
269
return -1;
270
}
271
272
if ((n = fread(buf, 1, sizeof(buf), f)) != -1) {
273
char *tmp;
274
275
buf[n-1] = '\0';
276
/** skip through pid and exec name. */
277
if ((tmp = strrchr(buf, ')')) != NULL) {
278
// skip the ')' and the following space
279
// but check that buffer is long enough
280
tmp += 2;
281
if (tmp < buf + n) {
282
n = vsscanf(tmp, fmt, args);
283
}
284
}
285
}
286
287
fclose(f);
288
289
return n;
290
}
291
292
static int SCANF_ARGS(2, 3) read_statdata(const char* procfile, _SCANFMT_ const char* fmt, ...) {
293
int n;
294
va_list args;
295
296
va_start(args, fmt);
297
n = vread_statdata(procfile, fmt, args);
298
va_end(args);
299
return n;
300
}
301
302
static FILE* open_statfile(void) {
303
FILE *f;
304
305
if ((f = fopen("/proc/stat", "r")) == NULL) {
306
static int haveWarned = 0;
307
if (!haveWarned) {
308
haveWarned = 1;
309
}
310
}
311
return f;
312
}
313
314
static void
315
next_line(FILE *f) {
316
int c;
317
do {
318
c = fgetc(f);
319
} while (c != '\n' && c != EOF);
320
}
321
322
/**
323
* Return the total number of ticks since the system was booted.
324
* If the usedTicks parameter is not NULL, it will be filled with
325
* the number of ticks spent on actual processes (user, system or
326
* nice processes) since system boot. Note that this is the total number
327
* of "executed" ticks on _all_ CPU:s, that is on a n-way system it is
328
* n times the number of ticks that has passed in clock time.
329
*
330
* Returns a negative value if the reading of the ticks failed.
331
*/
332
static OSReturn get_total_ticks(int which_logical_cpu, CPUPerfTicks* pticks) {
333
FILE* fh;
334
uint64_t userTicks, niceTicks, systemTicks, idleTicks;
335
uint64_t iowTicks = 0, irqTicks = 0, sirqTicks= 0;
336
int logical_cpu = -1;
337
const int expected_assign_count = (-1 == which_logical_cpu) ? 4 : 5;
338
int n;
339
340
if ((fh = open_statfile()) == NULL) {
341
return OS_ERR;
342
}
343
if (-1 == which_logical_cpu) {
344
n = fscanf(fh, "cpu " UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " "
345
UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT,
346
&userTicks, &niceTicks, &systemTicks, &idleTicks,
347
&iowTicks, &irqTicks, &sirqTicks);
348
} else {
349
// Move to next line
350
next_line(fh);
351
352
// find the line for requested cpu faster to just iterate linefeeds?
353
for (int i = 0; i < which_logical_cpu; i++) {
354
next_line(fh);
355
}
356
357
n = fscanf(fh, "cpu%u " UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " "
358
UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT,
359
&logical_cpu, &userTicks, &niceTicks,
360
&systemTicks, &idleTicks, &iowTicks, &irqTicks, &sirqTicks);
361
}
362
363
fclose(fh);
364
if (n < expected_assign_count || logical_cpu != which_logical_cpu) {
365
#ifdef DEBUG_LINUX_PROC_STAT
366
vm_fprintf(stderr, "[stat] read failed");
367
#endif
368
return OS_ERR;
369
}
370
371
#ifdef DEBUG_LINUX_PROC_STAT
372
vm_fprintf(stderr, "[stat] read "
373
UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " "
374
UINT64_FORMAT " " UINT64_FORMAT " " UINT64_FORMAT " \n",
375
userTicks, niceTicks, systemTicks, idleTicks,
376
iowTicks, irqTicks, sirqTicks);
377
#endif
378
379
pticks->used = userTicks + niceTicks;
380
pticks->usedKernel = systemTicks + irqTicks + sirqTicks;
381
pticks->total = userTicks + niceTicks + systemTicks + idleTicks +
382
iowTicks + irqTicks + sirqTicks;
383
384
return OS_OK;
385
}
386
387
388
static int get_systemtype(void) {
389
static int procEntriesType = UNDETECTED;
390
DIR *taskDir;
391
392
if (procEntriesType != UNDETECTED) {
393
return procEntriesType;
394
}
395
396
// Check whether we have a task subdirectory
397
if ((taskDir = opendir("/proc/self/task")) == NULL) {
398
procEntriesType = UNDETECTABLE;
399
} else {
400
// The task subdirectory exists; we're on a Linux >= 2.6 system
401
closedir(taskDir);
402
procEntriesType = LINUX26_NPTL;
403
}
404
405
return procEntriesType;
406
}
407
408
/** read user and system ticks from a named procfile, assumed to be in 'stat' format then. */
409
static int read_ticks(const char* procfile, uint64_t* userTicks, uint64_t* systemTicks) {
410
return read_statdata(procfile, "%*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u " UINT64_FORMAT " " UINT64_FORMAT,
411
userTicks, systemTicks);
412
}
413
414
/**
415
* Return the number of ticks spent in any of the processes belonging
416
* to the JVM on any CPU.
417
*/
418
static OSReturn get_jvm_ticks(CPUPerfTicks* pticks) {
419
uint64_t userTicks;
420
uint64_t systemTicks;
421
422
if (get_systemtype() != LINUX26_NPTL) {
423
return OS_ERR;
424
}
425
426
if (read_ticks("/proc/self/stat", &userTicks, &systemTicks) != 2) {
427
return OS_ERR;
428
}
429
430
// get the total
431
if (get_total_ticks(-1, pticks) != OS_OK) {
432
return OS_ERR;
433
}
434
435
pticks->used = userTicks;
436
pticks->usedKernel = systemTicks;
437
438
return OS_OK;
439
}
440
441
/**
442
* Return the load of the CPU as a double. 1.0 means the CPU process uses all
443
* available time for user or system processes, 0.0 means the CPU uses all time
444
* being idle.
445
*
446
* Returns a negative value if there is a problem in determining the CPU load.
447
*/
448
static double get_cpu_load(int which_logical_cpu, CPUPerfCounters* counters, double* pkernelLoad, CpuLoadTarget target) {
449
uint64_t udiff, kdiff, tdiff;
450
CPUPerfTicks* pticks;
451
CPUPerfTicks tmp;
452
double user_load;
453
454
*pkernelLoad = 0.0;
455
456
if (target == CPU_LOAD_VM_ONLY) {
457
pticks = &counters->jvmTicks;
458
} else if (-1 == which_logical_cpu) {
459
pticks = &counters->cpus[counters->nProcs];
460
} else {
461
pticks = &counters->cpus[which_logical_cpu];
462
}
463
464
tmp = *pticks;
465
466
if (target == CPU_LOAD_VM_ONLY) {
467
if (get_jvm_ticks(pticks) != OS_OK) {
468
return -1.0;
469
}
470
} else if (get_total_ticks(which_logical_cpu, pticks) != OS_OK) {
471
return -1.0;
472
}
473
474
// seems like we sometimes end up with less kernel ticks when
475
// reading /proc/self/stat a second time, timing issue between cpus?
476
if (pticks->usedKernel < tmp.usedKernel) {
477
kdiff = 0;
478
} else {
479
kdiff = pticks->usedKernel - tmp.usedKernel;
480
}
481
tdiff = pticks->total - tmp.total;
482
udiff = pticks->used - tmp.used;
483
484
if (tdiff == 0) {
485
return 0.0;
486
} else if (tdiff < (udiff + kdiff)) {
487
tdiff = udiff + kdiff;
488
}
489
*pkernelLoad = (kdiff / (double)tdiff);
490
// BUG9044876, normalize return values to sane values
491
*pkernelLoad = MAX2<double>(*pkernelLoad, 0.0);
492
*pkernelLoad = MIN2<double>(*pkernelLoad, 1.0);
493
494
user_load = (udiff / (double)tdiff);
495
user_load = MAX2<double>(user_load, 0.0);
496
user_load = MIN2<double>(user_load, 1.0);
497
498
return user_load;
499
}
500
501
static int SCANF_ARGS(1, 2) parse_stat(_SCANFMT_ const char* fmt, ...) {
502
FILE *f;
503
va_list args;
504
505
va_start(args, fmt);
506
507
if ((f = open_statfile()) == NULL) {
508
va_end(args);
509
return OS_ERR;
510
}
511
for (;;) {
512
char line[80];
513
if (fgets(line, sizeof(line), f) != NULL) {
514
if (vsscanf(line, fmt, args) == 1) {
515
fclose(f);
516
va_end(args);
517
return OS_OK;
518
}
519
} else {
520
fclose(f);
521
va_end(args);
522
return OS_ERR;
523
}
524
}
525
}
526
527
static int get_noof_context_switches(uint64_t* switches) {
528
return parse_stat("ctxt " UINT64_FORMAT "\n", switches);
529
}
530
531
/** returns boot time in _seconds_ since epoch */
532
static int get_boot_time(uint64_t* time) {
533
return parse_stat("btime " UINT64_FORMAT "\n", time);
534
}
535
536
static int perf_context_switch_rate(double* rate) {
537
static pthread_mutex_t contextSwitchLock = PTHREAD_MUTEX_INITIALIZER;
538
static uint64_t lastTime;
539
static uint64_t lastSwitches;
540
static double lastRate;
541
542
uint64_t lt = 0;
543
int res = 0;
544
545
if (lastTime == 0) {
546
uint64_t tmp;
547
if (get_boot_time(&tmp) < 0) {
548
return OS_ERR;
549
}
550
lt = tmp * 1000;
551
}
552
553
res = OS_OK;
554
555
pthread_mutex_lock(&contextSwitchLock);
556
{
557
558
uint64_t sw;
559
s8 t, d;
560
561
if (lastTime == 0) {
562
lastTime = lt;
563
}
564
565
t = os::javaTimeMillis();
566
d = t - lastTime;
567
568
if (d == 0) {
569
*rate = lastRate;
570
} else if (!get_noof_context_switches(&sw)) {
571
*rate = ( (double)(sw - lastSwitches) / d ) * 1000;
572
lastRate = *rate;
573
lastSwitches = sw;
574
lastTime = t;
575
} else {
576
*rate = 0;
577
res = OS_ERR;
578
}
579
if (*rate <= 0) {
580
*rate = 0;
581
lastRate = 0;
582
}
583
}
584
pthread_mutex_unlock(&contextSwitchLock);
585
586
return res;
587
}
588
589
class CPUPerformanceInterface::CPUPerformance : public CHeapObj<mtInternal> {
590
friend class CPUPerformanceInterface;
591
private:
592
CPUPerfCounters _counters;
593
594
int cpu_load(int which_logical_cpu, double* cpu_load);
595
int context_switch_rate(double* rate);
596
int cpu_load_total_process(double* cpu_load);
597
int cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad);
598
599
public:
600
CPUPerformance();
601
bool initialize();
602
~CPUPerformance();
603
};
604
605
CPUPerformanceInterface::CPUPerformance::CPUPerformance() {
606
_counters.nProcs = os::active_processor_count();
607
_counters.cpus = NULL;
608
}
609
610
bool CPUPerformanceInterface::CPUPerformance::initialize() {
611
size_t tick_array_size = (_counters.nProcs +1) * sizeof(CPUPerfTicks);
612
_counters.cpus = (CPUPerfTicks*)NEW_C_HEAP_ARRAY(char, tick_array_size, mtInternal);
613
if (NULL == _counters.cpus) {
614
return false;
615
}
616
memset(_counters.cpus, 0, tick_array_size);
617
618
// For the CPU load total
619
get_total_ticks(-1, &_counters.cpus[_counters.nProcs]);
620
621
// For each CPU
622
for (int i = 0; i < _counters.nProcs; i++) {
623
get_total_ticks(i, &_counters.cpus[i]);
624
}
625
// For JVM load
626
get_jvm_ticks(&_counters.jvmTicks);
627
628
// initialize context switch system
629
// the double is only for init
630
double init_ctx_switch_rate;
631
perf_context_switch_rate(&init_ctx_switch_rate);
632
633
return true;
634
}
635
636
CPUPerformanceInterface::CPUPerformance::~CPUPerformance() {
637
if (_counters.cpus != NULL) {
638
FREE_C_HEAP_ARRAY(char, _counters.cpus, mtInternal);
639
}
640
}
641
642
int CPUPerformanceInterface::CPUPerformance::cpu_load(int which_logical_cpu, double* cpu_load) {
643
double u, s;
644
u = get_cpu_load(which_logical_cpu, &_counters, &s, CPU_LOAD_GLOBAL);
645
if (u < 0) {
646
*cpu_load = 0.0;
647
return OS_ERR;
648
}
649
// Cap total systemload to 1.0
650
*cpu_load = MIN2<double>((u + s), 1.0);
651
return OS_OK;
652
}
653
654
int CPUPerformanceInterface::CPUPerformance::cpu_load_total_process(double* cpu_load) {
655
double u, s;
656
u = get_cpu_load(-1, &_counters, &s, CPU_LOAD_VM_ONLY);
657
if (u < 0) {
658
*cpu_load = 0.0;
659
return OS_ERR;
660
}
661
*cpu_load = u + s;
662
return OS_OK;
663
}
664
665
int CPUPerformanceInterface::CPUPerformance::cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad) {
666
double u, s, t;
667
668
assert(pjvmUserLoad != NULL, "pjvmUserLoad not inited");
669
assert(pjvmKernelLoad != NULL, "pjvmKernelLoad not inited");
670
assert(psystemTotalLoad != NULL, "psystemTotalLoad not inited");
671
672
u = get_cpu_load(-1, &_counters, &s, CPU_LOAD_VM_ONLY);
673
if (u < 0) {
674
*pjvmUserLoad = 0.0;
675
*pjvmKernelLoad = 0.0;
676
*psystemTotalLoad = 0.0;
677
return OS_ERR;
678
}
679
680
cpu_load(-1, &t);
681
// clamp at user+system and 1.0
682
if (u + s > t) {
683
t = MIN2<double>(u + s, 1.0);
684
}
685
686
*pjvmUserLoad = u;
687
*pjvmKernelLoad = s;
688
*psystemTotalLoad = t;
689
690
return OS_OK;
691
}
692
693
int CPUPerformanceInterface::CPUPerformance::context_switch_rate(double* rate) {
694
return perf_context_switch_rate(rate);
695
}
696
697
CPUPerformanceInterface::CPUPerformanceInterface() {
698
_impl = NULL;
699
}
700
701
bool CPUPerformanceInterface::initialize() {
702
_impl = new CPUPerformanceInterface::CPUPerformance();
703
return NULL == _impl ? false : _impl->initialize();
704
}
705
706
CPUPerformanceInterface::~CPUPerformanceInterface() {
707
if (_impl != NULL) {
708
delete _impl;
709
}
710
}
711
712
int CPUPerformanceInterface::cpu_load(int which_logical_cpu, double* cpu_load) const {
713
return _impl->cpu_load(which_logical_cpu, cpu_load);
714
}
715
716
int CPUPerformanceInterface::cpu_load_total_process(double* cpu_load) const {
717
return _impl->cpu_load_total_process(cpu_load);
718
}
719
720
int CPUPerformanceInterface::cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad) const {
721
return _impl->cpu_loads_process(pjvmUserLoad, pjvmKernelLoad, psystemTotalLoad);
722
}
723
724
int CPUPerformanceInterface::context_switch_rate(double* rate) const {
725
return _impl->context_switch_rate(rate);
726
}
727
728
class SystemProcessInterface::SystemProcesses : public CHeapObj<mtInternal> {
729
friend class SystemProcessInterface;
730
private:
731
class ProcessIterator : public CHeapObj<mtInternal> {
732
friend class SystemProcessInterface::SystemProcesses;
733
private:
734
DIR* _dir;
735
struct dirent* _entry;
736
bool _valid;
737
char _exeName[PATH_MAX];
738
char _exePath[PATH_MAX];
739
740
ProcessIterator();
741
~ProcessIterator();
742
bool initialize();
743
744
bool is_valid() const { return _valid; }
745
bool is_valid_entry(struct dirent* entry) const;
746
bool is_dir(const char* name) const;
747
int fsize(const char* name, uint64_t& size) const;
748
749
char* allocate_string(const char* str) const;
750
void get_exe_name();
751
char* get_exe_path();
752
char* get_cmdline();
753
754
int current(SystemProcess* process_info);
755
int next_process();
756
};
757
758
ProcessIterator* _iterator;
759
SystemProcesses();
760
bool initialize();
761
~SystemProcesses();
762
763
//information about system processes
764
int system_processes(SystemProcess** system_processes, int* no_of_sys_processes) const;
765
};
766
767
bool SystemProcessInterface::SystemProcesses::ProcessIterator::is_dir(const char* name) const {
768
struct stat mystat;
769
int ret_val = 0;
770
771
ret_val = stat(name, &mystat);
772
if (ret_val < 0) {
773
return false;
774
}
775
ret_val = S_ISDIR(mystat.st_mode);
776
return ret_val > 0;
777
}
778
779
int SystemProcessInterface::SystemProcesses::ProcessIterator::fsize(const char* name, uint64_t& size) const {
780
assert(name != NULL, "name pointer is NULL!");
781
size = 0;
782
struct stat fbuf;
783
784
if (stat(name, &fbuf) < 0) {
785
return OS_ERR;
786
}
787
size = fbuf.st_size;
788
return OS_OK;
789
}
790
791
// if it has a numeric name, is a directory and has a 'stat' file in it
792
bool SystemProcessInterface::SystemProcesses::ProcessIterator::is_valid_entry(struct dirent* entry) const {
793
char buffer[PATH_MAX];
794
uint64_t size = 0;
795
796
if (atoi(entry->d_name) != 0) {
797
jio_snprintf(buffer, PATH_MAX, "/proc/%s", entry->d_name);
798
buffer[PATH_MAX - 1] = '\0';
799
800
if (is_dir(buffer)) {
801
jio_snprintf(buffer, PATH_MAX, "/proc/%s/stat", entry->d_name);
802
buffer[PATH_MAX - 1] = '\0';
803
if (fsize(buffer, size) != OS_ERR) {
804
return true;
805
}
806
}
807
}
808
return false;
809
}
810
811
// get exe-name from /proc/<pid>/stat
812
void SystemProcessInterface::SystemProcesses::ProcessIterator::get_exe_name() {
813
FILE* fp;
814
char buffer[PATH_MAX];
815
816
jio_snprintf(buffer, PATH_MAX, "/proc/%s/stat", _entry->d_name);
817
buffer[PATH_MAX - 1] = '\0';
818
if ((fp = fopen(buffer, "r")) != NULL) {
819
if (fgets(buffer, PATH_MAX, fp) != NULL) {
820
char* start, *end;
821
// exe-name is between the first pair of ( and )
822
start = strchr(buffer, '(');
823
if (start != NULL && start[1] != '\0') {
824
start++;
825
end = strrchr(start, ')');
826
if (end != NULL) {
827
size_t len;
828
len = MIN2<size_t>(end - start, sizeof(_exeName) - 1);
829
memcpy(_exeName, start, len);
830
_exeName[len] = '\0';
831
}
832
}
833
}
834
fclose(fp);
835
}
836
}
837
838
// get command line from /proc/<pid>/cmdline
839
char* SystemProcessInterface::SystemProcesses::ProcessIterator::get_cmdline() {
840
FILE* fp;
841
char buffer[PATH_MAX];
842
char* cmdline = NULL;
843
844
jio_snprintf(buffer, PATH_MAX, "/proc/%s/cmdline", _entry->d_name);
845
buffer[PATH_MAX - 1] = '\0';
846
if ((fp = fopen(buffer, "r")) != NULL) {
847
size_t size = 0;
848
char dummy;
849
850
// find out how long the file is (stat always returns 0)
851
while (fread(&dummy, 1, 1, fp) == 1) {
852
size++;
853
}
854
if (size > 0) {
855
cmdline = NEW_C_HEAP_ARRAY(char, size + 1, mtInternal);
856
if (cmdline != NULL) {
857
cmdline[0] = '\0';
858
if (fseek(fp, 0, SEEK_SET) == 0) {
859
if (fread(cmdline, 1, size, fp) == size) {
860
// the file has the arguments separated by '\0',
861
// so we translate '\0' to ' '
862
for (size_t i = 0; i < size; i++) {
863
if (cmdline[i] == '\0') {
864
cmdline[i] = ' ';
865
}
866
}
867
cmdline[size] = '\0';
868
}
869
}
870
}
871
}
872
fclose(fp);
873
}
874
return cmdline;
875
}
876
877
// get full path to exe from /proc/<pid>/exe symlink
878
char* SystemProcessInterface::SystemProcesses::ProcessIterator::get_exe_path() {
879
char buffer[PATH_MAX];
880
881
jio_snprintf(buffer, PATH_MAX, "/proc/%s/exe", _entry->d_name);
882
buffer[PATH_MAX - 1] = '\0';
883
return realpath(buffer, _exePath);
884
}
885
886
char* SystemProcessInterface::SystemProcesses::ProcessIterator::allocate_string(const char* str) const {
887
if (str != NULL) {
888
size_t len = strlen(str);
889
char* tmp = NEW_C_HEAP_ARRAY(char, len+1, mtInternal);
890
strncpy(tmp, str, len);
891
tmp[len] = '\0';
892
return tmp;
893
}
894
return NULL;
895
}
896
897
int SystemProcessInterface::SystemProcesses::ProcessIterator::current(SystemProcess* process_info) {
898
if (!is_valid()) {
899
return OS_ERR;
900
}
901
902
process_info->set_pid(atoi(_entry->d_name));
903
904
get_exe_name();
905
process_info->set_name(allocate_string(_exeName));
906
907
if (get_exe_path() != NULL) {
908
process_info->set_path(allocate_string(_exePath));
909
}
910
911
char* cmdline = NULL;
912
cmdline = get_cmdline();
913
if (cmdline != NULL) {
914
process_info->set_command_line(allocate_string(cmdline));
915
FREE_C_HEAP_ARRAY(char, cmdline, mtInternal);
916
}
917
918
return OS_OK;
919
}
920
921
int SystemProcessInterface::SystemProcesses::ProcessIterator::next_process() {
922
if (!is_valid()) {
923
return OS_ERR;
924
}
925
926
do {
927
_entry = os::readdir(_dir);
928
if (_entry == NULL) {
929
// Error or reached end. Could use errno to distinguish those cases.
930
_valid = false;
931
return OS_ERR;
932
}
933
} while(!is_valid_entry(_entry));
934
935
_valid = true;
936
return OS_OK;
937
}
938
939
SystemProcessInterface::SystemProcesses::ProcessIterator::ProcessIterator() {
940
_dir = NULL;
941
_entry = NULL;
942
_valid = false;
943
}
944
945
bool SystemProcessInterface::SystemProcesses::ProcessIterator::initialize() {
946
_dir = os::opendir("/proc");
947
_entry = NULL;
948
_valid = true;
949
next_process();
950
951
return true;
952
}
953
954
SystemProcessInterface::SystemProcesses::ProcessIterator::~ProcessIterator() {
955
if (_dir != NULL) {
956
os::closedir(_dir);
957
}
958
}
959
960
SystemProcessInterface::SystemProcesses::SystemProcesses() {
961
_iterator = NULL;
962
}
963
964
bool SystemProcessInterface::SystemProcesses::initialize() {
965
_iterator = new SystemProcessInterface::SystemProcesses::ProcessIterator();
966
return NULL == _iterator ? false : _iterator->initialize();
967
}
968
969
SystemProcessInterface::SystemProcesses::~SystemProcesses() {
970
if (_iterator != NULL) {
971
delete _iterator;
972
}
973
}
974
975
int SystemProcessInterface::SystemProcesses::system_processes(SystemProcess** system_processes, int* no_of_sys_processes) const {
976
assert(system_processes != NULL, "system_processes pointer is NULL!");
977
assert(no_of_sys_processes != NULL, "system_processes counter pointers is NULL!");
978
assert(_iterator != NULL, "iterator is NULL!");
979
980
// initialize pointers
981
*no_of_sys_processes = 0;
982
*system_processes = NULL;
983
984
while (_iterator->is_valid()) {
985
SystemProcess* tmp = new SystemProcess();
986
_iterator->current(tmp);
987
988
//if already existing head
989
if (*system_processes != NULL) {
990
//move "first to second"
991
tmp->set_next(*system_processes);
992
}
993
// new head
994
*system_processes = tmp;
995
// increment
996
(*no_of_sys_processes)++;
997
// step forward
998
_iterator->next_process();
999
}
1000
return OS_OK;
1001
}
1002
1003
int SystemProcessInterface::system_processes(SystemProcess** system_procs, int* no_of_sys_processes) const {
1004
return _impl->system_processes(system_procs, no_of_sys_processes);
1005
}
1006
1007
SystemProcessInterface::SystemProcessInterface() {
1008
_impl = NULL;
1009
}
1010
1011
bool SystemProcessInterface::initialize() {
1012
_impl = new SystemProcessInterface::SystemProcesses();
1013
return NULL == _impl ? false : _impl->initialize();
1014
}
1015
1016
SystemProcessInterface::~SystemProcessInterface() {
1017
if (_impl != NULL) {
1018
delete _impl;
1019
}
1020
}
1021
1022
CPUInformationInterface::CPUInformationInterface() {
1023
_cpu_info = NULL;
1024
}
1025
1026
bool CPUInformationInterface::initialize() {
1027
_cpu_info = new CPUInformation();
1028
if (NULL == _cpu_info) {
1029
return false;
1030
}
1031
_cpu_info->set_number_of_hardware_threads(VM_Version_Ext::number_of_threads());
1032
_cpu_info->set_number_of_cores(VM_Version_Ext::number_of_cores());
1033
_cpu_info->set_number_of_sockets(VM_Version_Ext::number_of_sockets());
1034
_cpu_info->set_cpu_name(VM_Version_Ext::cpu_name());
1035
_cpu_info->set_cpu_description(VM_Version_Ext::cpu_description());
1036
1037
return true;
1038
}
1039
1040
CPUInformationInterface::~CPUInformationInterface() {
1041
if (_cpu_info != NULL) {
1042
if (_cpu_info->cpu_name() != NULL) {
1043
const char* cpu_name = _cpu_info->cpu_name();
1044
FREE_C_HEAP_ARRAY(char, cpu_name, mtInternal);
1045
_cpu_info->set_cpu_name(NULL);
1046
}
1047
if (_cpu_info->cpu_description() != NULL) {
1048
const char* cpu_desc = _cpu_info->cpu_description();
1049
FREE_C_HEAP_ARRAY(char, cpu_desc, mtInternal);
1050
_cpu_info->set_cpu_description(NULL);
1051
}
1052
delete _cpu_info;
1053
}
1054
}
1055
1056
int CPUInformationInterface::cpu_information(CPUInformation& cpu_info) {
1057
if (_cpu_info == NULL) {
1058
return OS_ERR;
1059
}
1060
1061
cpu_info = *_cpu_info; // shallow copy assignment
1062
return OS_OK;
1063
}
1064
1065
class NetworkPerformanceInterface::NetworkPerformance : public CHeapObj<mtInternal> {
1066
friend class NetworkPerformanceInterface;
1067
private:
1068
NetworkPerformance();
1069
NetworkPerformance(const NetworkPerformance& rhs); // no impl
1070
NetworkPerformance& operator=(const NetworkPerformance& rhs); // no impl
1071
bool initialize();
1072
~NetworkPerformance();
1073
int64_t read_counter(const char* iface, const char* counter) const;
1074
int network_utilization(NetworkInterface** network_interfaces) const;
1075
};
1076
1077
NetworkPerformanceInterface::NetworkPerformance::NetworkPerformance() {
1078
1079
}
1080
1081
bool NetworkPerformanceInterface::NetworkPerformance::initialize() {
1082
return true;
1083
}
1084
1085
NetworkPerformanceInterface::NetworkPerformance::~NetworkPerformance() {
1086
}
1087
1088
int64_t NetworkPerformanceInterface::NetworkPerformance::read_counter(const char* iface, const char* counter) const {
1089
char buf[128];
1090
1091
snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics/%s", iface, counter);
1092
1093
int fd = open(buf, O_RDONLY);
1094
if (fd == -1) {
1095
return -1;
1096
}
1097
1098
ssize_t num_bytes = read(fd, buf, sizeof(buf));
1099
close(fd);
1100
if ((num_bytes == -1) || (num_bytes >= static_cast<ssize_t>(sizeof(buf))) || (num_bytes < 1)) {
1101
return -1;
1102
}
1103
1104
buf[num_bytes] = '\0';
1105
int64_t value = strtoll(buf, NULL, 10);
1106
1107
return value;
1108
}
1109
1110
int NetworkPerformanceInterface::NetworkPerformance::network_utilization(NetworkInterface** network_interfaces) const
1111
{
1112
ifaddrs* addresses;
1113
ifaddrs* cur_address;
1114
1115
if (getifaddrs(&addresses) != 0) {
1116
return OS_ERR;
1117
}
1118
1119
NetworkInterface* ret = NULL;
1120
for (cur_address = addresses; cur_address != NULL; cur_address = cur_address->ifa_next) {
1121
if ((cur_address->ifa_addr == NULL) || (cur_address->ifa_addr->sa_family != AF_PACKET)) {
1122
continue;
1123
}
1124
1125
int64_t bytes_in = read_counter(cur_address->ifa_name, "rx_bytes");
1126
int64_t bytes_out = read_counter(cur_address->ifa_name, "tx_bytes");
1127
1128
NetworkInterface* cur = new NetworkInterface(cur_address->ifa_name, bytes_in, bytes_out, ret);
1129
ret = cur;
1130
}
1131
1132
freeifaddrs(addresses);
1133
*network_interfaces = ret;
1134
1135
return OS_OK;
1136
}
1137
1138
NetworkPerformanceInterface::NetworkPerformanceInterface() {
1139
_impl = NULL;
1140
}
1141
1142
NetworkPerformanceInterface::~NetworkPerformanceInterface() {
1143
if (_impl != NULL) {
1144
delete _impl;
1145
}
1146
}
1147
1148
bool NetworkPerformanceInterface::initialize() {
1149
_impl = new NetworkPerformanceInterface::NetworkPerformance();
1150
return _impl != NULL && _impl->initialize();
1151
}
1152
1153
int NetworkPerformanceInterface::network_utilization(NetworkInterface** network_interfaces) const {
1154
return _impl->network_utilization(network_interfaces);
1155
}
1156
1157