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