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