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