src/os/aix/vm/os_perf_aix.cpp

Tue, 21 Apr 2020 12:03:29 +0200

author
clanger
date
Tue, 21 Apr 2020 12:03:29 +0200
changeset 9907
35063c223567
parent 9858
b985cbb00e68
permissions
-rw-r--r--

8241902: AIX Build broken after integration of JDK-8223147 (JFR Backport)
Reviewed-by: mdoerr, apetushkov

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

mercurial