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