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