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