1 /*
   2  * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "precompiled.hpp"
  26 #include "iphlp_interface.hpp"
  27 #include "logging/log.hpp"
  28 #include "memory/allocation.inline.hpp"
  29 #include "memory/resourceArea.hpp"
  30 #include "pdh_interface.hpp"
  31 #include "runtime/os_perf.hpp"
  32 #include "runtime/os.hpp"
  33 #include "utilities/macros.hpp"
  34 #include "vm_version_ext_x86.hpp"
  35 #include <math.h>
  36 #include <psapi.h>
  37 #include <TlHelp32.h>
  38 
  39 /*
  40  * Windows provides a vast plethora of performance objects and counters,
  41  * consumption of which is assisted using the Performance Data Helper (PDH) interface.
  42  * We import a selected few api entry points from PDH, see pdh_interface.hpp.
  43  *
  44  * The code located in this file is to a large extent an abstraction over much of the
  45  * plumbing needed to start consuming an object and/or counter of choice.
  46  *
  47  */
  48 
  49  /*
  50  * How to use:
  51  * 1. Create query
  52  * 2. Add counters to the query
  53  * 3. Collect the performance data using the query
  54  * 4. Display the performance data using the counters associated with the query
  55  * 5. Destroy query (counter destruction implied)
  56  */
  57 
  58 /*
  59  * Every PDH artifact, like processor, process, thread, memory, and so forth are
  60  * identified with an index that is always the same irrespective
  61  * of the localized version of the operating system or service pack installed.
  62  * INFO: Using PDH APIs Correctly in a Localized Language (Q287159)
  63  *   http://support.microsoft.com/default.aspx?scid=kb;EN-US;q287159
  64  *
  65  * To find the correct index for an object or counter, inspect the registry key / value:
  66  * [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\009\Counter]
  67  *
  68  * some common PDH indexes
  69  */
  70 static const DWORD PDH_PROCESSOR_IDX = 238;
  71 static const DWORD PDH_PROCESSOR_TIME_IDX = 6;
  72 static const DWORD PDH_PRIV_PROCESSOR_TIME_IDX = 144;
  73 static const DWORD PDH_PROCESS_IDX = 230;
  74 static const DWORD PDH_ID_PROCESS_IDX = 784;
  75 static const DWORD PDH_CONTEXT_SWITCH_RATE_IDX = 146;
  76 static const DWORD PDH_SYSTEM_IDX = 2;
  77 
  78 /* useful pdh fmt's */
  79 static const char* const OBJECT_COUNTER_FMT = "\\%s\\%s";
  80 static const size_t OBJECT_COUNTER_FMT_LEN = 2;
  81 static const char* const OBJECT_WITH_INSTANCES_COUNTER_FMT = "\\%s(%s)\\%s";
  82 static const size_t OBJECT_WITH_INSTANCES_COUNTER_FMT_LEN = 4;
  83 static const char* const PROCESS_OBJECT_INSTANCE_COUNTER_FMT = "\\%s(%s#%s)\\%s";
  84 static const size_t PROCESS_OBJECT_INSTANCE_COUNTER_FMT_LEN = 5;
  85 
  86 static const char* process_image_name = NULL; // for example, "java" but could have another image name
  87 static char* pdh_IDProcess_counter_fmt = NULL;   // "\Process(java#%d)\ID Process" */
  88 
  89 // Need to limit how often we update a query to minimize the heisenberg effect.
  90 // (PDH behaves erratically if the counters are queried too often, especially counters that
  91 // store and use values from two consecutive updates, like cpu load.)
  92 static const int min_update_interval_millis = 500;
  93 
  94 /*
  95 * Structs for PDH queries.
  96 */
  97 typedef struct {
  98   HQUERY query;
  99   s8     lastUpdate; // Last time query was updated (current millis).
 100 } UpdateQueryS, *UpdateQueryP;
 101 
 102 
 103 typedef struct {
 104   UpdateQueryS query;
 105   HCOUNTER     counter;
 106   bool         initialized;
 107 } CounterQueryS, *CounterQueryP;
 108 
 109 typedef struct {
 110   UpdateQueryS query;
 111   HCOUNTER*    counters;
 112   int          noOfCounters;
 113   bool         initialized;
 114 } MultiCounterQueryS, *MultiCounterQueryP;
 115 
 116 typedef struct {
 117   MultiCounterQueryP queries;
 118   int                size;
 119   bool               initialized;
 120 } MultiCounterQuerySetS, *MultiCounterQuerySetP;
 121 
 122 typedef struct {
 123   MultiCounterQuerySetS set;
 124   int                   process_index;
 125 } ProcessQueryS, *ProcessQueryP;
 126 
 127 static void pdh_cleanup(HQUERY* const query, HCOUNTER* const counter) {
 128   if (counter != NULL && *counter != NULL) {
 129     PdhDll::PdhRemoveCounter(*counter);
 130     *counter = NULL;
 131   }
 132   if (query != NULL && *query != NULL) {
 133     PdhDll::PdhCloseQuery(*query);
 134     *query = NULL;
 135   }
 136 }
 137 
 138 static CounterQueryP create_counter_query() {
 139   CounterQueryP const query = NEW_C_HEAP_OBJ(CounterQueryS, mtInternal);
 140   memset(query, 0, sizeof(CounterQueryS));
 141   return query;
 142 }
 143 
 144 static void destroy_counter_query(CounterQueryP query) {
 145   assert(query != NULL, "invariant");
 146   pdh_cleanup(&query->query.query, &query->counter);
 147   FREE_C_HEAP_OBJ(query);
 148 }
 149 
 150 static MultiCounterQueryP create_multi_counter_query() {
 151   MultiCounterQueryP const query = NEW_C_HEAP_ARRAY(MultiCounterQueryS, 1, mtInternal);
 152   memset(query, 0, sizeof(MultiCounterQueryS));
 153   return query;
 154 }
 155 
 156 static void destroy_counter_query(MultiCounterQueryP counter_query) {
 157   if (counter_query != NULL) {
 158     for (int i = 0; i < counter_query->noOfCounters; ++i) {
 159       pdh_cleanup(NULL, &counter_query->counters[i]);
 160     }
 161     FREE_C_HEAP_ARRAY(char, counter_query->counters);
 162     pdh_cleanup(&counter_query->query.query, NULL);
 163     FREE_C_HEAP_ARRAY(MultiCounterQueryS, counter_query);
 164   }
 165 }
 166 
 167 static void destroy_multi_counter_query(MultiCounterQuerySetP counter_query_set) {
 168   for (int i = 0; i < counter_query_set->size; i++) {
 169     for (int j = 0; j < counter_query_set->queries[i].noOfCounters; ++j) {
 170       pdh_cleanup(NULL, &counter_query_set->queries[i].counters[j]);
 171     }
 172     FREE_C_HEAP_ARRAY(char, counter_query_set->queries[i].counters);
 173     pdh_cleanup(&counter_query_set->queries[i].query.query, NULL);
 174   }
 175   FREE_C_HEAP_ARRAY(MultiCounterQueryS, counter_query_set->queries);
 176 }
 177 
 178 static void destroy_counter_query(MultiCounterQuerySetP counter_query_set) {
 179   destroy_multi_counter_query(counter_query_set);
 180   FREE_C_HEAP_ARRAY(MultiCounterQuerySetS, counter_query_set);
 181 }
 182 
 183 static void destroy_counter_query(ProcessQueryP process_query) {
 184   destroy_multi_counter_query(&process_query->set);
 185   FREE_C_HEAP_OBJ(process_query);
 186 }
 187 
 188 static int open_query(HQUERY* query) {
 189   return PdhDll::PdhOpenQuery(NULL, 0, query);
 190 }
 191 
 192 template <typename QueryP>
 193 static int open_query(QueryP query) {
 194   return open_query(&query->query);
 195 }
 196 
 197 static int allocate_counters(MultiCounterQueryP query, size_t nofCounters) {
 198   assert(query != NULL, "invariant");
 199   assert(!query->initialized, "invariant");
 200   assert(0 == query->noOfCounters, "invariant");
 201   assert(query->counters == NULL, "invariant");
 202   query->counters = NEW_C_HEAP_ARRAY(HCOUNTER, nofCounters, mtInternal);
 203   if (query->counters == NULL) {
 204     return OS_ERR;
 205   }
 206   memset(query->counters, 0, nofCounters * sizeof(HCOUNTER));
 207   query->noOfCounters = (int)nofCounters;
 208   return OS_OK;
 209 }
 210 
 211 static int allocate_counters(MultiCounterQuerySetP query_set, size_t nofCounters) {
 212   assert(query_set != NULL, "invariant");
 213   assert(!query_set->initialized, "invariant");
 214   for (int i = 0; i < query_set->size; ++i) {
 215     if (allocate_counters(&query_set->queries[i], nofCounters) != OS_OK) {
 216       return OS_ERR;
 217     }
 218   }
 219   return OS_OK;
 220 }
 221 
 222 static int allocate_counters(ProcessQueryP process_query, size_t nofCounters) {
 223   assert(process_query != NULL, "invariant");
 224   return allocate_counters(&process_query->set, nofCounters);
 225 }
 226 
 227 static void deallocate_counters(MultiCounterQueryP query) {
 228   FREE_C_HEAP_ARRAY(char, query->counters);
 229   query->counters = NULL;
 230   query->noOfCounters = 0;


 231 }
 232 
 233 static OSReturn add_counter(UpdateQueryP query, HCOUNTER* counter, const char* path, bool first_sample_on_init) {
 234   assert(query != NULL, "invariant");
 235   assert(counter != NULL, "invariant");
 236   assert(path != NULL, "invariant");
 237   if (query->query == NULL) {
 238     if (open_query(query) != ERROR_SUCCESS) {
 239       return OS_ERR;
 240     }
 241   }
 242   assert(query->query != NULL, "invariant");
 243   PDH_STATUS status = PdhDll::PdhAddCounter(query->query, path, 0, counter);
 244   if (PDH_CSTATUS_NO_OBJECT == status || PDH_CSTATUS_NO_COUNTER == status) {
 245     return OS_ERR;
 246   }
 247   /*
 248   * According to the MSDN documentation, rate counters must be read twice:
 249   *
 250   * "Obtaining the value of rate counters such as Page faults/sec requires that
 251   *  PdhCollectQueryData be called twice, with a specific time interval between
 252   *  the two calls, before calling PdhGetFormattedCounterValue. Call Sleep to
 253   *  implement the waiting period between the two calls to PdhCollectQueryData."
 254   *
 255   *  Take the first sample here already to allow for the next "real" sample
 256   *  to succeed.
 257   */
 258   if (first_sample_on_init) {
 259     PdhDll::PdhCollectQueryData(query->query);
 260   }
 261   return OS_OK;
 262 }
 263 
 264 template <typename QueryP>
 265 static OSReturn add_counter(QueryP counter_query, HCOUNTER* counter, const char* path, bool first_sample_on_init) {
 266   assert(counter_query != NULL, "invariant");
 267   assert(counter != NULL, "invariant");
 268   assert(path != NULL, "invariant");
 269   return add_counter(&counter_query->query, counter, path, first_sample_on_init);
 270 }
 271 
 272 static OSReturn add_counter(CounterQueryP counter_query, const char* path, bool first_sample_on_init) {
 273   if (add_counter(counter_query, &counter_query->counter, path, first_sample_on_init) != OS_OK) {
 274     // performance counter might be disabled in the registry
 275     return OS_ERR;
 276   }
 277   counter_query->initialized = true;
 278   return OS_OK;
 279 }
 280 
 281 static OSReturn add_process_counter(MultiCounterQueryP query, int slot_index, const char* path, bool first_sample_on_init) {
 282   assert(query != NULL, "invariant");
 283   assert(slot_index < query->noOfCounters, "invariant");
 284   assert(query->counters[slot_index] == NULL, "invariant");
 285   const OSReturn ret = add_counter(query, &query->counters[slot_index], path, first_sample_on_init);
 286   if (OS_OK == ret) {
 287     if (slot_index + 1 == query->noOfCounters) {
 288       query->initialized = true;
 289     }
 290   }
 291   return ret;
 292 }
 293 
 294 static int collect_query_data(UpdateQueryP update_query) {
 295   assert(update_query != NULL, "invariant");
 296   const s8 now = os::javaTimeMillis();
 297   if (now - update_query->lastUpdate > min_update_interval_millis) {
 298     if (PdhDll::PdhCollectQueryData(update_query->query) != ERROR_SUCCESS) {
 299       return OS_ERR;
 300     }
 301     update_query->lastUpdate = now;
 302   }
 303   return OS_OK;
 304 }
 305 
 306 template <typename Query>
 307 static int collect_query_data(Query* counter_query) {
 308   assert(counter_query != NULL, "invariant");
 309   return collect_query_data(&counter_query->query);
 310 }
 311 
 312 static int formatted_counter_value(HCOUNTER counter, DWORD format, PDH_FMT_COUNTERVALUE* const value) {
 313   assert(value != NULL, "invariant");
 314   if (PdhDll::PdhGetFormattedCounterValue(counter, format, NULL, value) != ERROR_SUCCESS) {
 315     return OS_ERR;
 316   }
 317   return OS_OK;
 318 }
 319 
 320 /*
 321 * Working against the Process object and it's related counters is inherently problematic
 322 * when using the PDH API:
 323 *
 324 * Using PDH, a process is not primarily identified by the process id,
 325 * but with a sequential number, for example \Process(java#0), \Process(java#1), ...
 326 * The really bad part is that this list is reset as soon as a process exits:
 327 * If \Process(java#1) exits, \Process(java#3) now becomes \Process(java#2) etc.
 328 *
 329 * The PDH api requires a process identifier to be submitted when registering
 330 * a query, but as soon as the list resets, the query is invalidated (since the name changed).
 331 *
 332 * Solution:
 333 * The #number identifier for a Process query can only decrease after process creation.
 334 *
 335 * We therefore create an array of counter queries for all process object instances
 336 * up to and including ourselves:
 337 *
 338 * Ex. we come in as third process instance (java#2), we then create and register
 339 * queries for the following Process object instances:
 340 * java#0, java#1, java#2
 341 *
 342 * current_query_index_for_process() keeps track of the current "correct" query
 343 * (in order to keep this index valid when the list resets from underneath,
 344 * ensure to call current_query_index_for_process() before every query involving
 345 * Process object instance data).
 346 *
 347 * if unable to query, returns OS_ERR(-1)
 348 */
 349 static int current_query_index_for_process() {
 350   assert(process_image_name != NULL, "invariant");
 351   assert(pdh_IDProcess_counter_fmt != NULL, "invariant");
 352   HQUERY tmpQuery = NULL;
 353   if (open_query(&tmpQuery) != ERROR_SUCCESS) {
 354     return OS_ERR;
 355   }
 356   char counter[512];
 357   HCOUNTER handle_counter = NULL;
 358   // iterate over all instance indexes and try to find our own pid
 359   for (int index = 0; index < max_intx; index++) {
 360     jio_snprintf(counter, sizeof(counter) - 1, pdh_IDProcess_counter_fmt, index);
 361     assert(strlen(counter) < sizeof(counter), "invariant");
 362     if (PdhDll::PdhAddCounter(tmpQuery, counter, 0, &handle_counter) != ERROR_SUCCESS) {
 363       pdh_cleanup(&tmpQuery, &handle_counter);
 364       return OS_ERR;
 365     }
 366     const PDH_STATUS res = PdhDll::PdhCollectQueryData(tmpQuery);
 367     if (res == PDH_INVALID_HANDLE || res == PDH_NO_DATA) {
 368       pdh_cleanup(&tmpQuery, &handle_counter);
 369       return OS_ERR;
 370     } else {
 371       PDH_FMT_COUNTERVALUE counter_value;
 372       formatted_counter_value(handle_counter, PDH_FMT_LONG, &counter_value);
 373       pdh_cleanup(NULL, &handle_counter);
 374       if ((LONG)os::current_process_id() == counter_value.longValue) {
 375         pdh_cleanup(&tmpQuery, NULL);
 376         return index;
 377       }
 378     }
 379   }
 380   pdh_cleanup(&tmpQuery, NULL);
 381   return OS_ERR;
 382 }
 383 
 384 static ProcessQueryP create_process_query() {
 385   const int current_process_idx = current_query_index_for_process();
 386   if (OS_ERR == current_process_idx) {
 387     return NULL;
 388   }
 389   ProcessQueryP const process_query = NEW_C_HEAP_OBJ(ProcessQueryS, mtInternal);
 390   memset(process_query, 0, sizeof(ProcessQueryS));
 391   process_query->set.queries = NEW_C_HEAP_ARRAY(MultiCounterQueryS, current_process_idx + 1, mtInternal);
 392   memset(process_query->set.queries, 0, sizeof(MultiCounterQueryS) * (current_process_idx + 1));
 393   process_query->process_index = current_process_idx;
 394   process_query->set.size = current_process_idx + 1;
 395   assert(process_query->set.size > process_query->process_index, "invariant");
 396   return process_query;
 397 }
 398 
 399 static MultiCounterQueryP current_process_counter_query(ProcessQueryP process_query) {
 400   assert(process_query != NULL, "invariant");
 401   assert(process_query->process_index < process_query->set.size, "invariant");
 402   return &process_query->set.queries[process_query->process_index];
 403 }
 404 
 405 static void clear_multi_counter(MultiCounterQueryP query) {
 406   for (int i = 0; i < query->noOfCounters; ++i) {
 407     pdh_cleanup(NULL, &query->counters[i]);
 408   }
 409   pdh_cleanup(&query->query.query, NULL);
 410   query->initialized = false;
 411 }
 412 
 413 static int ensure_valid_process_query_index(ProcessQueryP process_query) {
 414   assert(process_query != NULL, "invariant");
 415   const int previous_process_idx = process_query->process_index;
 416   if (previous_process_idx == 0) {
 417     return previous_process_idx;
 418   }
 419   const int current_process_idx = current_query_index_for_process();
 420   if (current_process_idx == previous_process_idx || OS_ERR == current_process_idx ||
 421     current_process_idx >= process_query->set.size) {
 422     return previous_process_idx;
 423   }
 424 
 425   assert(current_process_idx >= 0 && current_process_idx < process_query->set.size, "out of bounds!");
 426   while (current_process_idx < process_query->set.size - 1) {
 427     const int new_size = --process_query->set.size;
 428     clear_multi_counter(&process_query->set.queries[new_size]);
 429   }
 430   assert(current_process_idx < process_query->set.size, "invariant");
 431   process_query->process_index = current_process_idx;
 432   return current_process_idx;
 433 }
 434 
 435 static MultiCounterQueryP current_process_query(ProcessQueryP process_query) {
 436   assert(process_query != NULL, "invariant");
 437   const int current_process_idx = ensure_valid_process_query_index(process_query);
 438   assert(current_process_idx == process_query->process_index, "invariant");
 439   assert(current_process_idx < process_query->set.size, "invariant");
 440   return &process_query->set.queries[current_process_idx];
 441 }
 442 
 443 static int collect_process_query_data(ProcessQueryP process_query) {
 444   assert(process_query != NULL, "invariant");
 445   return collect_query_data(current_process_query(process_query));
 446 }
 447 
 448 static int query_process_counter(ProcessQueryP process_query, int slot_index, DWORD format, PDH_FMT_COUNTERVALUE* const value) {
 449   MultiCounterQueryP const current_query = current_process_counter_query(process_query);
 450   assert(current_query != NULL, "invariant");
 451   assert(slot_index < current_query->noOfCounters, "invariant");
 452   assert(current_query->counters[slot_index] != NULL, "invariant");
 453   return formatted_counter_value(current_query->counters[slot_index], format, value);
 454 }
 455 
 456 /*
 457  * Construct a fully qualified PDH path
 458  *
 459  * @param objectName   a PDH Object string representation(required)
 460  * @param counterName  a PDH Counter string representation(required)
 461  * @param imageName    a process image name string, ex. "java" (opt)
 462  * @param instance     an instance string, ex. "0", "1", ... (opt)
 463  * @return             the fully qualified PDH path.
 464  *
 465  * Caller will need a ResourceMark.
 466  *
 467  * (PdhMakeCounterPath() seems buggy on concatenating instances, hence this function instead)
 468  */
 469 static const char* make_fully_qualified_counter_path(const char* object_name,
 470                                                      const char* counter_name,
 471                                                      const char* image_name = NULL,
 472                                                      const char* instance = NULL) {
 473   assert(object_name != NULL, "invariant");
 474   assert(counter_name != NULL, "invariant");
 475   size_t full_counter_path_len = strlen(object_name) + strlen(counter_name);
 476 
 477   char* full_counter_path;
 478   size_t jio_snprintf_result = 0;
 479   if (image_name) {
 480     /*
 481     * For paths using the "Process" Object.
 482     *
 483     * Examples:
 484     * form:   "\object_name(image_name#instance)\counter_name"
 485     * actual: "\Process(java#2)\ID Process"
 486     */
 487     full_counter_path_len += PROCESS_OBJECT_INSTANCE_COUNTER_FMT_LEN;
 488     full_counter_path_len += strlen(image_name);
 489     /*
 490     * image_name must be passed together with an associated
 491     * instance "number" ("0", "1", "2", ...).
 492     * This is required in order to create valid "Process" Object paths.
 493     *
 494     * Examples: "\Process(java#0)", \Process(java#1"), ...
 495     */
 496     assert(instance != NULL, "invariant");
 497     full_counter_path_len += strlen(instance);
 498     full_counter_path = NEW_RESOURCE_ARRAY_RETURN_NULL(char, full_counter_path_len + 1);
 499     if (full_counter_path == NULL) {
 500       return NULL;
 501     }
 502     jio_snprintf_result = jio_snprintf(full_counter_path,
 503                                        full_counter_path_len + 1,
 504                                        PROCESS_OBJECT_INSTANCE_COUNTER_FMT,
 505                                        object_name,
 506                                        image_name,
 507                                        instance,
 508                                        counter_name);
 509   } else {
 510     if (instance) {
 511       /*
 512       * For paths where the Object has multiple instances.
 513       *
 514       * Examples:
 515       * form:   "\object_name(instance)\counter_name"
 516       * actual: "\Processor(0)\% Privileged Time"
 517       */
 518       full_counter_path_len += strlen(instance);
 519       full_counter_path_len += OBJECT_WITH_INSTANCES_COUNTER_FMT_LEN;
 520     } else {
 521       /*
 522       * For "normal" paths.
 523       *
 524       * Examples:
 525       * form:   "\object_name\counter_name"
 526       * actual: "\Memory\Available Mbytes"
 527       */
 528       full_counter_path_len += OBJECT_COUNTER_FMT_LEN;
 529     }
 530     full_counter_path = NEW_RESOURCE_ARRAY_RETURN_NULL(char, full_counter_path_len + 1);
 531     if (full_counter_path == NULL) {
 532       return NULL;
 533     }
 534     if (instance) {
 535       jio_snprintf_result = jio_snprintf(full_counter_path,
 536                                          full_counter_path_len + 1,
 537                                          OBJECT_WITH_INSTANCES_COUNTER_FMT,
 538                                          object_name,
 539                                          instance,
 540                                          counter_name);
 541     } else {
 542       jio_snprintf_result = jio_snprintf(full_counter_path,
 543                                          full_counter_path_len + 1,
 544                                          OBJECT_COUNTER_FMT,
 545                                          object_name,
 546                                          counter_name);
 547     }
 548   }
 549   assert(full_counter_path_len == jio_snprintf_result, "invariant");
 550   return full_counter_path;
 551 }
 552 
 553 static void log_invalid_pdh_index(DWORD index) {
 554   log_warning(os)("Unable to resolve PDH index: (%ld)", index);
 555   log_warning(os)("Please check the registry if this performance object/counter is disabled");
 556 }
 557 
 558 static bool is_valid_pdh_index(DWORD index) {
 559   DWORD dummy = 0;
 560   if (PdhDll::PdhLookupPerfNameByIndex(NULL, index, NULL, &dummy) != PDH_MORE_DATA) {
 561     log_invalid_pdh_index(index);
 562     return false;
 563   }
 564   return true;
 565 }
 566 
 567 /*
 568  * Maps an index to a resource area allocated string for the localized PDH artifact.
 569  *
 570  * Caller will need a ResourceMark.
 571  *
 572  * @param index    the counter index as specified in the registry
 573  * @param ppBuffer pointer to a char*
 574  * @return         OS_OK if successful, OS_ERR on failure.
 575  */
 576 static OSReturn lookup_name_by_index(DWORD index, char** p_string) {
 577   assert(p_string != NULL, "invariant");
 578   if (!is_valid_pdh_index(index)) {
 579     return OS_ERR;
 580   }
 581   // determine size needed
 582   DWORD size = 0;
 583   PDH_STATUS status = PdhDll::PdhLookupPerfNameByIndex(NULL, index, NULL, &size);
 584   assert(status == PDH_MORE_DATA, "invariant");
 585   *p_string = NEW_RESOURCE_ARRAY_RETURN_NULL(char, size);
 586   if (*p_string== NULL) {
 587     return OS_ERR;
 588   }
 589   if (PdhDll::PdhLookupPerfNameByIndex(NULL, index, *p_string, &size) != ERROR_SUCCESS) {
 590     return OS_ERR;
 591   }
 592   if (0 == size || *p_string == NULL) {
 593     return OS_ERR;
 594   }
 595   // windows vista does not null-terminate the string (although the docs says it will)
 596   (*p_string)[size - 1] = '\0';
 597   return OS_OK;
 598 }
 599 
 600 static const char* copy_string_to_c_heap(const char* string) {
 601   assert(string != NULL, "invariant");
 602   const size_t len = strlen(string);
 603   char* const cheap_allocated_string = NEW_C_HEAP_ARRAY(char, len + 1, mtInternal);
 604   if (NULL == cheap_allocated_string) {
 605     return NULL;
 606   }
 607   strncpy(cheap_allocated_string, string, len + 1);
 608   return cheap_allocated_string;
 609 }
 610 
 611 /*
 612 * Maps an index to a resource area allocated string for the localized PDH artifact.
 613 *
 614 * Caller will need a ResourceMark.
 615 *
 616 * @param index    the counter index as specified in the registry
 617 * @return         localized pdh artifact string if successful, NULL on failure.
 618 */
 619 static const char* pdh_localized_artifact(DWORD pdh_artifact_index) {
 620   char* pdh_localized_artifact_string = NULL;
 621   // get localized name from pdh artifact index
 622   if (lookup_name_by_index(pdh_artifact_index, &pdh_localized_artifact_string) != OS_OK) {
 623     return NULL;
 624   }
 625   return pdh_localized_artifact_string;
 626 }
 627 
 628 /*
 629  * Returns the PDH string identifying the current process image name.
 630  * Use this prefix when getting counters from the PDH process object
 631  * representing your process.
 632  * Ex. "Process(java#0)\Virtual Bytes" - where "java" is the PDH process
 633  * image description.
 634  *
 635  * Caller needs ResourceMark.
 636  *
 637  * @return the process image description. NULL if the call failed.
 638 */
 639 static const char* pdh_process_image_name() {
 640   char* module_name = NEW_RESOURCE_ARRAY_RETURN_NULL(char, MAX_PATH);
 641   if (NULL == module_name) {
 642     return NULL;
 643   }
 644   // Find our module name and use it to extract the image name used by PDH
 645   DWORD getmfn_return = GetModuleFileName(NULL, module_name, MAX_PATH);
 646   if (getmfn_return >= MAX_PATH || 0 == getmfn_return) {
 647     return NULL;
 648   }
 649   if (os::get_last_error() == ERROR_INSUFFICIENT_BUFFER) {
 650     return NULL;
 651   }
 652   char* process_image_name = strrchr(module_name, '\\'); //drop path
 653   process_image_name++;                                  //skip slash
 654   char* dot_pos = strrchr(process_image_name, '.');      //drop .exe
 655   dot_pos[0] = '\0';
 656   return process_image_name;
 657 }
 658 
 659 static void deallocate_pdh_constants() {
 660   FREE_C_HEAP_ARRAY(char, process_image_name);
 661   process_image_name = NULL;
 662   FREE_C_HEAP_ARRAY(char, pdh_IDProcess_counter_fmt);
 663   pdh_IDProcess_counter_fmt = NULL;




 664 }
 665 
 666 static int allocate_pdh_constants() {
 667   assert(process_image_name == NULL, "invariant");
 668   const char* pdh_image_name = pdh_process_image_name();
 669   if (pdh_image_name == NULL) {
 670     return OS_ERR;
 671   }
 672   process_image_name = copy_string_to_c_heap(pdh_image_name);
 673 
 674   const char* pdh_localized_process_object = pdh_localized_artifact(PDH_PROCESS_IDX);
 675   if (pdh_localized_process_object == NULL) {
 676     return OS_ERR;
 677   }
 678 
 679   const char* pdh_localized_IDProcess_counter = pdh_localized_artifact(PDH_ID_PROCESS_IDX);
 680   if (pdh_localized_IDProcess_counter == NULL) {
 681     return OS_ERR;
 682   }
 683 
 684   size_t pdh_IDProcess_counter_fmt_len = strlen(process_image_name);
 685   pdh_IDProcess_counter_fmt_len += strlen(pdh_localized_process_object);
 686   pdh_IDProcess_counter_fmt_len += strlen(pdh_localized_IDProcess_counter);
 687   pdh_IDProcess_counter_fmt_len += PROCESS_OBJECT_INSTANCE_COUNTER_FMT_LEN;
 688   pdh_IDProcess_counter_fmt_len += 2; // "%d"
 689 
 690   assert(pdh_IDProcess_counter_fmt == NULL, "invariant");
 691   pdh_IDProcess_counter_fmt = NEW_C_HEAP_ARRAY_RETURN_NULL(char, pdh_IDProcess_counter_fmt_len + 1, mtInternal);
 692   if (pdh_IDProcess_counter_fmt == NULL) {
 693     return OS_ERR;
 694   }
 695 
 696   /* "\Process(java#%d)\ID Process" */
 697   const size_t len = jio_snprintf(pdh_IDProcess_counter_fmt,
 698                                   pdh_IDProcess_counter_fmt_len + 1,
 699                                   PROCESS_OBJECT_INSTANCE_COUNTER_FMT,
 700                                   pdh_localized_process_object,
 701                                   process_image_name,
 702                                   "%d",
 703                                   pdh_localized_IDProcess_counter);
 704 
 705   assert(pdh_IDProcess_counter_fmt != NULL, "invariant");
 706   assert(len == pdh_IDProcess_counter_fmt_len, "invariant");
 707   return OS_OK;
 708 }
 709 
 710 /*
 711  * Enuerate the Processor PDH object and returns a buffer containing the enumerated instances.
 712  * Caller needs ResourceMark;
 713  *
 714  * @return  buffer if successful, NULL on failure.
 715 */
 716 static const char* enumerate_cpu_instances() {
 717   char* processor; //'Processor' == PDH_PROCESSOR_IDX
 718   if (lookup_name_by_index(PDH_PROCESSOR_IDX, &processor) != OS_OK) {
 719     return NULL;
 720   }
 721   DWORD c_size = 0;
 722   DWORD i_size = 0;
 723   // enumerate all processors.
 724   PDH_STATUS pdhStat = PdhDll::PdhEnumObjectItems(NULL, // reserved
 725                                                   NULL, // local machine
 726                                                   processor, // object to enumerate
 727                                                   NULL,
 728                                                   &c_size,
 729                                                   NULL, // instance buffer is NULL and
 730                                                   &i_size,  // pass 0 length in order to get the required size
 731                                                   PERF_DETAIL_WIZARD, // counter detail level
 732                                                   0);
 733   if (PdhDll::PdhStatusFail((pdhStat))) {
 734     return NULL;
 735   }
 736   char* const instances = NEW_RESOURCE_ARRAY_RETURN_NULL(char, i_size);
 737   if (instances == NULL) {
 738     return NULL;
 739   }
 740   c_size = 0;
 741   pdhStat = PdhDll::PdhEnumObjectItems(NULL, // reserved
 742                                        NULL, // local machine
 743                                        processor, // object to enumerate
 744                                        NULL,
 745                                        &c_size,
 746                                        instances, // now instance buffer is allocated to be filled in
 747                                        &i_size, // and the required size is known
 748                                        PERF_DETAIL_WIZARD, // counter detail level
 749                                        0);
 750   if (PdhDll::PdhStatusFail((pdhStat))) {
 751     return NULL;
 752   }
 753   return instances;
 754 }
 755 
 756 static int count_logical_cpus(const char* instances) {
 757   assert(instances != NULL, "invariant");
 758   // count logical instances.
 759   DWORD count;
 760   char* tmp;
 761   for (count = 0, tmp = const_cast<char*>(instances); *tmp != '\0'; tmp = &tmp[strlen(tmp) + 1], count++);
 762   // PDH reports an instance for each logical processor plus an instance for the total (_Total)
 763   assert(count == os::processor_count() + 1, "invalid enumeration!");
 764   return count - 1;
 765 }
 766 
 767 static int number_of_logical_cpus() {
 768   static int numberOfCPUS = 0;
 769   if (numberOfCPUS == 0) {
 770     const char* instances = enumerate_cpu_instances();
 771     if (instances == NULL) {
 772       return OS_ERR;
 773     }
 774     numberOfCPUS = count_logical_cpus(instances);
 775   }
 776   return numberOfCPUS;
 777 }
 778 
 779 static double cpu_factor() {
 780   static DWORD  numCpus = 0;
 781   static double cpuFactor = .0;
 782   if (numCpus == 0) {
 783     numCpus = number_of_logical_cpus();
 784     assert(os::processor_count() <= (int)numCpus, "invariant");
 785     cpuFactor = numCpus * 100;
 786   }
 787   return cpuFactor;
 788 }
 789 
 790 static void log_error_message_on_no_PDH_artifact(const char* full_counter_name) {
 791   log_warning(os)("Unable to register PDH query for \"%s\"", full_counter_name);
 792   log_warning(os)("Please check the registry if this performance object/counter is disabled");
 793 }
 794 
 795 static int initialize_cpu_query_counters(MultiCounterQueryP cpu_query, DWORD pdh_counter_idx) {
 796   assert(cpu_query != NULL, "invariant");
 797   assert(cpu_query->counters != NULL, "invariant");
 798   char* processor; //'Processor' == PDH_PROCESSOR_IDX
 799   if (lookup_name_by_index(PDH_PROCESSOR_IDX, &processor) != OS_OK) {
 800     return OS_ERR;
 801   }
 802   char* counter_name = NULL;
 803   if (lookup_name_by_index(pdh_counter_idx, &counter_name) != OS_OK) {
 804     return OS_ERR;
 805   }
 806   if (cpu_query->query.query == NULL) {
 807     if (open_query(cpu_query)) {
 808       return OS_ERR;
 809     }
 810   }
 811   assert(cpu_query->query.query != NULL, "invariant");
 812   size_t counter_len = strlen(processor);
 813   counter_len += strlen(counter_name);
 814   counter_len += OBJECT_WITH_INSTANCES_COUNTER_FMT_LEN; // "\\%s(%s)\\%s"
 815 
 816   DWORD index;
 817   char* tmp;
 818   const char* instances = enumerate_cpu_instances();
 819   for (index = 0, tmp = const_cast<char*>(instances); *tmp != '\0'; tmp = &tmp[strlen(tmp) + 1], index++) {
 820     const size_t tmp_len = strlen(tmp);
 821     char* counter_path = NEW_RESOURCE_ARRAY_RETURN_NULL(char, counter_len + tmp_len + 1);
 822     if (counter_path == NULL) {
 823       return OS_ERR;
 824     }
 825     const size_t jio_snprintf_result = jio_snprintf(counter_path,
 826                                                     counter_len + tmp_len + 1,
 827                                                     OBJECT_WITH_INSTANCES_COUNTER_FMT,
 828                                                     processor,
 829                                                     tmp, // instance "0", "1", .."_Total"
 830                                                     counter_name);
 831     assert(counter_len + tmp_len == jio_snprintf_result, "invariant");
 832     if (add_counter(cpu_query, &cpu_query->counters[index], counter_path, false) != OS_OK) {
 833       // performance counter is disabled in registry and not accessible via PerfLib
 834       log_error_message_on_no_PDH_artifact(counter_path);
 835       // return OS_OK to have the system continue to run without the missing counter
 836       return OS_OK;
 837     }
 838   }
 839   cpu_query->initialized = true;
 840   // Query once to initialize the counters which require at least two samples
 841   // (like the % CPU usage) to calculate correctly.
 842   collect_query_data(cpu_query);
 843   return OS_OK;
 844 }
 845 
 846 static int initialize_cpu_query(MultiCounterQueryP cpu_query, DWORD pdh_counter_idx) {
 847   assert(cpu_query != NULL, "invariant");
 848   assert(!cpu_query->initialized, "invariant");
 849   const int logical_cpu_count = number_of_logical_cpus();
 850   assert(logical_cpu_count >= os::processor_count(), "invariant");
 851   // we also add another counter for instance "_Total"
 852   if (allocate_counters(cpu_query, logical_cpu_count + 1) != OS_OK) {
 853     return OS_ERR;
 854   }
 855   assert(cpu_query->noOfCounters == logical_cpu_count + 1, "invariant");
 856   return initialize_cpu_query_counters(cpu_query, pdh_counter_idx);
 857 }
 858 
 859 static int initialize_process_counter(ProcessQueryP process_query, int slot_index, DWORD pdh_counter_index) {
 860   char* localized_process_object;
 861   if (lookup_name_by_index(PDH_PROCESS_IDX, &localized_process_object) != OS_OK) {
 862     return OS_ERR;
 863   }
 864   assert(localized_process_object != NULL, "invariant");
 865   char* localized_counter_name;
 866   if (lookup_name_by_index(pdh_counter_index, &localized_counter_name) != OS_OK) {
 867     return OS_ERR;
 868   }
 869   assert(localized_counter_name != NULL, "invariant");
 870   for (int i = 0; i < process_query->set.size; ++i) {
 871     char instanceIndexBuffer[32];
 872     const char* counter_path = make_fully_qualified_counter_path(localized_process_object,
 873                                                                  localized_counter_name,
 874                                                                  process_image_name,
 875                                                                  itoa(i, instanceIndexBuffer, 10));
 876     if (counter_path == NULL) {
 877       return OS_ERR;
 878     }
 879     MultiCounterQueryP const query = &process_query->set.queries[i];
 880     if (add_process_counter(query, slot_index, counter_path, true)) {
 881       return OS_ERR;
 882     }
 883   }
 884   return OS_OK;
 885 }
 886 
 887 static CounterQueryP create_counter_query(DWORD pdh_object_idx, DWORD pdh_counter_idx) {
 888   if (!((is_valid_pdh_index(pdh_object_idx) && is_valid_pdh_index(pdh_counter_idx)))) {
 889     return NULL;
 890   }
 891   CounterQueryP const query = create_counter_query();
 892   const char* object = pdh_localized_artifact(pdh_object_idx);
 893   assert(object != NULL, "invariant");
 894   const char* counter = pdh_localized_artifact(pdh_counter_idx);
 895   assert(counter != NULL, "invariant");
 896   const char* full_counter_path = make_fully_qualified_counter_path(object, counter);
 897   assert(full_counter_path != NULL, "invariant");
 898   add_counter(query, full_counter_path, true);
 899   return query;
 900 }
 901 
 902 static void deallocate() {
 903   deallocate_pdh_constants();
 904   PdhDll::PdhDetach();
 905 }
 906 
 907 static LONG critical_section = 0;
 908 static LONG reference_count = 0;
 909 static bool pdh_initialized = false;
 910 
 911 static void on_initialization_failure() {
 912   // still holder of critical section
 913   deallocate();
 914   InterlockedExchangeAdd(&reference_count, -1);
 915 }
 916 
 917 static OSReturn initialize() {
 918   ResourceMark rm;
 919   if (!PdhDll::PdhAttach()) {
 920     return OS_ERR;
 921   }
 922   if (allocate_pdh_constants() != OS_OK) {
 923     on_initialization_failure();
 924     return OS_ERR;
 925   }
 926   return OS_OK;
 927 }
 928 
 929 /*
 930 * Helper to initialize the PDH library, function pointers, constants and counters.
 931 *
 932 * Reference counting allows for unloading of pdh.dll granted all sessions use the pair:
 933 *
 934 *   pdh_acquire();
 935 *   pdh_release();
 936 *
 937 * @return  OS_OK if successful, OS_ERR on failure.
 938 */
 939 static bool pdh_acquire() {
 940   while (InterlockedCompareExchange(&critical_section, 1, 0) == 1);
 941   InterlockedExchangeAdd(&reference_count, 1);
 942   if (pdh_initialized) {
 943     return true;
 944   }
 945   const OSReturn ret = initialize();
 946   if (OS_OK == ret) {
 947     pdh_initialized = true;
 948   }
 949   while (InterlockedCompareExchange(&critical_section, 0, 1) == 0);
 950   return ret == OS_OK;
 951 }
 952 
 953 static void pdh_release() {
 954   while (InterlockedCompareExchange(&critical_section, 1, 0) == 1);
 955   const LONG prev_ref_count = InterlockedExchangeAdd(&reference_count, -1);
 956   if (1 == prev_ref_count) {
 957     deallocate();
 958     pdh_initialized = false;
 959   }
 960   while (InterlockedCompareExchange(&critical_section, 0, 1) == 0);
 961 }
 962 
 963 class CPUPerformanceInterface::CPUPerformance : public CHeapObj<mtInternal> {
 964   friend class CPUPerformanceInterface;
 965  private:
 966   CounterQueryP _context_switches;
 967   ProcessQueryP _process_cpu_load;
 968   MultiCounterQueryP _machine_cpu_load;
 969 
 970   int cpu_load(int which_logical_cpu, double* cpu_load);
 971   int context_switch_rate(double* rate);
 972   int cpu_load_total_process(double* cpu_load);
 973   int cpu_loads_process(double* jvm_user_load, double* jvm_kernel_load, double* psystemTotalLoad);
 974   CPUPerformance();
 975   ~CPUPerformance();
 976   bool initialize();
 977 };
 978 
 979 class SystemProcessInterface::SystemProcesses : public CHeapObj<mtInternal> {
 980   friend class SystemProcessInterface;
 981  private:
 982   class ProcessIterator : public CHeapObj<mtInternal> {
 983     friend class SystemProcessInterface::SystemProcesses;
 984    private:
 985     HANDLE         _hProcessSnap;
 986     PROCESSENTRY32 _pe32;
 987     BOOL           _valid;
 988     char           _exePath[MAX_PATH];
 989     ProcessIterator();
 990     ~ProcessIterator();
 991     bool initialize();
 992 
 993     int current(SystemProcess* const process_info);
 994     int next_process();
 995     bool is_valid() const { return _valid != FALSE; }
 996     char* allocate_string(const char* str) const;
 997     int snapshot();
 998   };
 999 
1000   ProcessIterator* _iterator;
1001   SystemProcesses();
1002   ~SystemProcesses();
1003   bool initialize();
1004 
1005   // information about system processes
1006   int system_processes(SystemProcess** system_processes, int* no_of_sys_processes) const;
1007 };
1008 
1009 CPUPerformanceInterface::CPUPerformance::CPUPerformance() : _context_switches(NULL), _process_cpu_load(NULL), _machine_cpu_load(NULL) {}
1010 
1011 bool CPUPerformanceInterface::CPUPerformance::initialize() {
1012   if (!pdh_acquire()) {
1013     return true;
1014   }
1015   _context_switches = create_counter_query(PDH_SYSTEM_IDX, PDH_CONTEXT_SWITCH_RATE_IDX);
1016   _process_cpu_load = create_process_query();
1017   if (_process_cpu_load == NULL) {
1018     return true;
1019   }
1020   if (allocate_counters(_process_cpu_load, 2) != OS_OK) {
1021     return true;
1022   }
1023   if (initialize_process_counter(_process_cpu_load, 0, PDH_PROCESSOR_TIME_IDX) != OS_OK) {
1024     return true;
1025   }
1026   if (initialize_process_counter(_process_cpu_load, 1, PDH_PRIV_PROCESSOR_TIME_IDX) != OS_OK) {
1027     return true;
1028   }
1029   _process_cpu_load->set.initialized = true;
1030   _machine_cpu_load = create_multi_counter_query();
1031   if (_machine_cpu_load == NULL) {
1032     return true;
1033   }
1034   initialize_cpu_query(_machine_cpu_load, PDH_PROCESSOR_TIME_IDX);
1035   return true;
1036 }
1037 
1038 CPUPerformanceInterface::CPUPerformance::~CPUPerformance() {
1039   if (_context_switches != NULL) {
1040     destroy_counter_query(_context_switches);
1041     _context_switches = NULL;
1042   }
1043   if (_process_cpu_load != NULL) {
1044     destroy_counter_query(_process_cpu_load);
1045     _process_cpu_load = NULL;
1046   }
1047   if (_machine_cpu_load != NULL) {
1048     destroy_counter_query(_machine_cpu_load);
1049     _machine_cpu_load = NULL;
1050   }
1051   pdh_release();
1052 }
1053 
1054 CPUPerformanceInterface::CPUPerformanceInterface() {
1055   _impl = NULL;
1056 }
1057 
1058 bool CPUPerformanceInterface::initialize() {
1059   _impl = new CPUPerformanceInterface::CPUPerformance();
1060   return _impl != NULL && _impl->initialize();
1061 }
1062 
1063 CPUPerformanceInterface::~CPUPerformanceInterface() {
1064   if (_impl != NULL) {
1065     delete _impl;
1066   }
1067 }
1068 
1069 int CPUPerformanceInterface::cpu_load(int which_logical_cpu, double* cpu_load) const {
1070   return _impl->cpu_load(which_logical_cpu, cpu_load);
1071 }
1072 
1073 int CPUPerformanceInterface::context_switch_rate(double* rate) const {
1074   return _impl->context_switch_rate(rate);
1075 }
1076 
1077 int CPUPerformanceInterface::cpu_load_total_process(double* cpu_load) const {
1078   return _impl->cpu_load_total_process(cpu_load);
1079 }
1080 
1081 int CPUPerformanceInterface::cpu_loads_process(double* pjvmUserLoad,
1082                                                double* pjvmKernelLoad,
1083                                                double* psystemTotalLoad) const {
1084   return _impl->cpu_loads_process(pjvmUserLoad, pjvmKernelLoad, psystemTotalLoad);
1085 }
1086 
1087 int CPUPerformanceInterface::CPUPerformance::cpu_load(int which_logical_cpu, double* cpu_load) {
1088   *cpu_load = .0;
1089   if (_machine_cpu_load == NULL || !_machine_cpu_load->initialized) {
1090     return OS_ERR;
1091   }
1092   assert(_machine_cpu_load != NULL, "invariant");
1093   assert(which_logical_cpu < _machine_cpu_load->noOfCounters, "invariant");
1094 
1095   if (collect_query_data(_machine_cpu_load)) {
1096     return OS_ERR;
1097   }
1098   // -1 is total (all cpus)
1099   const int counter_idx = -1 == which_logical_cpu ? _machine_cpu_load->noOfCounters - 1 : which_logical_cpu;
1100   PDH_FMT_COUNTERVALUE counter_value;
1101   formatted_counter_value(_machine_cpu_load->counters[counter_idx], PDH_FMT_DOUBLE, &counter_value);
1102   *cpu_load = counter_value.doubleValue / 100;
1103   return OS_OK;
1104 }
1105 
1106 int CPUPerformanceInterface::CPUPerformance::cpu_load_total_process(double* cpu_load) {
1107   *cpu_load = .0;
1108   if (_process_cpu_load == NULL || !_process_cpu_load->set.initialized) {
1109     return OS_ERR;
1110   }
1111   assert(_process_cpu_load != NULL, "invariant");
1112   if (collect_process_query_data(_process_cpu_load)) {
1113     return OS_ERR;
1114   }
1115   PDH_FMT_COUNTERVALUE counter_value;
1116   if (query_process_counter(_process_cpu_load, 0, PDH_FMT_DOUBLE | PDH_FMT_NOCAP100, &counter_value) != OS_OK) {
1117     return OS_ERR;
1118   }
1119   double process_load = counter_value.doubleValue / cpu_factor();
1120   process_load = MIN2<double>(1, process_load);
1121   process_load = MAX2<double>(0, process_load);
1122   *cpu_load = process_load;
1123   return OS_OK;
1124 }
1125 
1126 int CPUPerformanceInterface::CPUPerformance::cpu_loads_process(double* pjvmUserLoad,
1127                                                                double* pjvmKernelLoad,
1128                                                                double* psystemTotalLoad) {
1129   assert(pjvmUserLoad != NULL, "pjvmUserLoad is NULL!");
1130   assert(pjvmKernelLoad != NULL, "pjvmKernelLoad is NULL!");
1131   assert(psystemTotalLoad != NULL, "psystemTotalLoad is NULL!");
1132   *pjvmUserLoad = .0;
1133   *pjvmKernelLoad = .0;
1134   *psystemTotalLoad = .0;
1135 
1136   if (_process_cpu_load == NULL || !_process_cpu_load->set.initialized) {
1137     return OS_ERR;
1138   }
1139   assert(_process_cpu_load != NULL, "invariant");
1140   if (collect_process_query_data(_process_cpu_load)) {
1141     return OS_ERR;
1142   }
1143   double process_load = .0;
1144   PDH_FMT_COUNTERVALUE counter_value;
1145   // Read  PDH_PROCESSOR_TIME_IDX
1146   if (query_process_counter(_process_cpu_load, 0, PDH_FMT_DOUBLE | PDH_FMT_NOCAP100, &counter_value) != OS_OK) {
1147     return OS_ERR;
1148   }
1149   process_load = counter_value.doubleValue / cpu_factor();
1150   process_load = MIN2<double>(1, process_load);
1151   process_load = MAX2<double>(0, process_load);
1152   // Read PDH_PRIV_PROCESSOR_TIME_IDX
1153   if (query_process_counter(_process_cpu_load, 1, PDH_FMT_DOUBLE | PDH_FMT_NOCAP100, &counter_value) != OS_OK) {
1154     return OS_ERR;
1155   }
1156   double kernel_load = counter_value.doubleValue / cpu_factor();
1157   kernel_load = MIN2<double>(1, kernel_load);
1158   kernel_load = MAX2<double>(0, kernel_load);
1159   *pjvmKernelLoad = kernel_load;
1160 
1161   double user_load = process_load - kernel_load;
1162   user_load = MIN2<double>(1, user_load);
1163   user_load = MAX2<double>(0, user_load);
1164   *pjvmUserLoad = user_load;
1165 
1166   if (collect_query_data(_machine_cpu_load)) {
1167     return OS_ERR;
1168   }
1169   if (formatted_counter_value(_machine_cpu_load->counters[_machine_cpu_load->noOfCounters - 1], PDH_FMT_DOUBLE, &counter_value) != OS_OK) {
1170     return OS_ERR;
1171   }
1172   double machine_load = counter_value.doubleValue / 100;
1173   assert(machine_load >= 0, "machine_load is negative!");
1174   // clamp at user+system and 1.0
1175   if (*pjvmKernelLoad + *pjvmUserLoad > machine_load) {
1176     machine_load = MIN2(*pjvmKernelLoad + *pjvmUserLoad, 1.0);
1177   }
1178   *psystemTotalLoad = machine_load;
1179   return OS_OK;
1180 }
1181 
1182 int CPUPerformanceInterface::CPUPerformance::context_switch_rate(double* rate) {
1183   assert(rate != NULL, "invariant");
1184   *rate = .0;
1185   if (_context_switches == NULL || !_context_switches->initialized) {
1186     return OS_ERR;
1187   }
1188   assert(_context_switches != NULL, "invariant");
1189   if (collect_query_data(_context_switches) != OS_OK) {
1190     return OS_ERR;
1191   }
1192   PDH_FMT_COUNTERVALUE counter_value;
1193   if (formatted_counter_value(_context_switches->counter, PDH_FMT_DOUBLE, &counter_value) != OS_OK) {
1194     return OS_ERR;
1195   }
1196   *rate = counter_value.doubleValue;
1197   return OS_OK;
1198 }
1199 
1200 SystemProcessInterface::SystemProcesses::ProcessIterator::ProcessIterator() {
1201   _hProcessSnap = INVALID_HANDLE_VALUE;
1202   _valid = FALSE;
1203   _pe32.dwSize = sizeof(PROCESSENTRY32);
1204 }
1205 
1206 bool SystemProcessInterface::SystemProcesses::ProcessIterator::initialize() {
1207   return true;
1208 }
1209 
1210 int SystemProcessInterface::SystemProcesses::ProcessIterator::snapshot() {
1211   // take snapshot of all process in the system
1212   _hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1213   if (_hProcessSnap == INVALID_HANDLE_VALUE) {
1214     return OS_ERR;
1215   }
1216   // step to first process
1217   _valid = Process32First(_hProcessSnap, &_pe32);
1218   return is_valid() ? OS_OK : OS_ERR;
1219 }
1220 
1221 SystemProcessInterface::SystemProcesses::ProcessIterator::~ProcessIterator() {
1222   if (_hProcessSnap != INVALID_HANDLE_VALUE) {
1223     CloseHandle(_hProcessSnap);
1224   }
1225 }
1226 
1227 int SystemProcessInterface::SystemProcesses::ProcessIterator::current(SystemProcess* process_info) {
1228   assert(is_valid(), "no current process to be fetched!");
1229   assert(process_info != NULL, "process_info is NULL!");
1230   char* exePath = NULL;
1231   HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, _pe32.th32ProcessID);
1232   if (hProcess != NULL) {
1233     HMODULE hMod;
1234     DWORD cbNeeded;
1235     if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded) != 0) {
1236       if (GetModuleFileNameExA(hProcess, hMod, _exePath, sizeof(_exePath)) != 0) {
1237         exePath = _exePath;
1238       }
1239     }
1240     CloseHandle (hProcess);
1241   }
1242   process_info->set_pid((int)_pe32.th32ProcessID);
1243   process_info->set_name(allocate_string(_pe32.szExeFile));
1244   process_info->set_path(allocate_string(exePath));
1245   return OS_OK;
1246 }
1247 
1248 char* SystemProcessInterface::SystemProcesses::ProcessIterator::allocate_string(const char* str) const {
1249   if (str != NULL) {
1250     return os::strdup_check_oom(str, mtInternal);
1251   }
1252   return NULL;
1253 }
1254 
1255 int SystemProcessInterface::SystemProcesses::ProcessIterator::next_process() {
1256   _valid = Process32Next(_hProcessSnap, &_pe32);
1257   return OS_OK;
1258 }
1259 
1260 SystemProcessInterface::SystemProcesses::SystemProcesses() {
1261   _iterator = NULL;
1262 }
1263 
1264 bool SystemProcessInterface::SystemProcesses::initialize() {
1265   _iterator = new SystemProcessInterface::SystemProcesses::ProcessIterator();
1266   return _iterator != NULL && _iterator->initialize();
1267 }
1268 
1269 SystemProcessInterface::SystemProcesses::~SystemProcesses() {
1270   if (_iterator != NULL) {
1271     delete _iterator;
1272     _iterator = NULL;
1273   }
1274 }
1275 
1276 int SystemProcessInterface::SystemProcesses::system_processes(SystemProcess** system_processes,
1277                                                               int* no_of_sys_processes) const {
1278   assert(system_processes != NULL, "system_processes pointer is NULL!");
1279   assert(no_of_sys_processes != NULL, "system_processes counter pointers is NULL!");
1280   assert(_iterator != NULL, "iterator is NULL!");
1281 
1282   // initialize pointers
1283   *no_of_sys_processes = 0;
1284   *system_processes = NULL;
1285 
1286   // take process snapshot
1287   if (_iterator->snapshot() != OS_OK) {
1288     return OS_ERR;
1289   }
1290 
1291   while (_iterator->is_valid()) {
1292     SystemProcess* tmp = new SystemProcess();
1293     _iterator->current(tmp);
1294 
1295     //if already existing head
1296     if (*system_processes != NULL) {
1297       //move "first to second"
1298       tmp->set_next(*system_processes);
1299     }
1300     // new head
1301     *system_processes = tmp;
1302     // increment
1303     (*no_of_sys_processes)++;
1304     // step forward
1305     _iterator->next_process();
1306   }
1307   return OS_OK;
1308 }
1309 
1310 int SystemProcessInterface::system_processes(SystemProcess** system_procs,
1311                                              int* no_of_sys_processes) const {
1312   return _impl->system_processes(system_procs, no_of_sys_processes);
1313 }
1314 
1315 SystemProcessInterface::SystemProcessInterface() {
1316   _impl = NULL;
1317 }
1318 
1319 bool SystemProcessInterface::initialize() {
1320   _impl = new SystemProcessInterface::SystemProcesses();
1321   return _impl != NULL && _impl->initialize();
1322 }
1323 
1324 SystemProcessInterface::~SystemProcessInterface() {
1325   if (_impl != NULL) {
1326     delete _impl;
1327   }
1328 }
1329 
1330 CPUInformationInterface::CPUInformationInterface() {
1331   _cpu_info = NULL;
1332 }
1333 
1334 bool CPUInformationInterface::initialize() {
1335   _cpu_info = new CPUInformation();
1336   if (NULL == _cpu_info) {
1337     return false;
1338   }
1339   _cpu_info->set_number_of_hardware_threads(VM_Version_Ext::number_of_threads());
1340   _cpu_info->set_number_of_cores(VM_Version_Ext::number_of_cores());
1341   _cpu_info->set_number_of_sockets(VM_Version_Ext::number_of_sockets());
1342   _cpu_info->set_cpu_name(VM_Version_Ext::cpu_name());
1343   _cpu_info->set_cpu_description(VM_Version_Ext::cpu_description());
1344   return true;
1345 }
1346 
1347 CPUInformationInterface::~CPUInformationInterface() {
1348   if (_cpu_info != NULL) {
1349     FREE_C_HEAP_ARRAY(char, _cpu_info->cpu_name());
1350     _cpu_info->set_cpu_name(NULL);
1351     FREE_C_HEAP_ARRAY(char, _cpu_info->cpu_description());
1352     _cpu_info->set_cpu_description(NULL);






1353     delete _cpu_info;
1354     _cpu_info = NULL;
1355   }
1356 }
1357 
1358 int CPUInformationInterface::cpu_information(CPUInformation& cpu_info) {
1359   if (NULL == _cpu_info) {
1360     return OS_ERR;
1361   }
1362   cpu_info = *_cpu_info; // shallow copy assignment
1363   return OS_OK;
1364 }
1365 
1366 class NetworkPerformanceInterface::NetworkPerformance : public CHeapObj<mtInternal> {
1367   friend class NetworkPerformanceInterface;
1368  private:
1369   bool _iphlp_attached;
1370 
1371   NetworkPerformance();
1372   NetworkPerformance(const NetworkPerformance& rhs); // no impl
1373   NetworkPerformance& operator=(const NetworkPerformance& rhs); // no impl
1374   bool initialize();
1375   ~NetworkPerformance();
1376   int network_utilization(NetworkInterface** network_interfaces) const;
1377 };
1378 
1379 NetworkPerformanceInterface::NetworkPerformance::NetworkPerformance()
1380 : _iphlp_attached(false) {
1381 }
1382 
1383 bool NetworkPerformanceInterface::NetworkPerformance::initialize() {
1384   _iphlp_attached = IphlpDll::IphlpAttach();
1385   return _iphlp_attached;
1386 }
1387 
1388 NetworkPerformanceInterface::NetworkPerformance::~NetworkPerformance() {
1389   if (_iphlp_attached) {
1390     IphlpDll::IphlpDetach();
1391   }
1392 }
1393 
1394 int NetworkPerformanceInterface::NetworkPerformance::network_utilization(NetworkInterface** network_interfaces) const {
1395   MIB_IF_TABLE2* table;
1396 
1397   if (IphlpDll::GetIfTable2(&table) != NO_ERROR) {
1398     return OS_ERR;
1399   }
1400 
1401   NetworkInterface* ret = NULL;
1402   for (ULONG i = 0; i < table->NumEntries; ++i) {
1403     if (table->Table[i].InterfaceAndOperStatusFlags.FilterInterface) {
1404       continue;
1405     }
1406 
1407     char buf[256];
1408     if (WideCharToMultiByte(CP_UTF8, 0, table->Table[i].Description, -1, buf, sizeof(buf), NULL, NULL) == 0) {
1409       continue;
1410     }
1411 
1412     NetworkInterface* cur = new NetworkInterface(buf, table->Table[i].InOctets, table->Table[i].OutOctets, ret);
1413     ret = cur;
1414   }
1415 
1416   IphlpDll::FreeMibTable(table);
1417   *network_interfaces = ret;
1418 
1419   return OS_OK;
1420 }
1421 
1422 NetworkPerformanceInterface::NetworkPerformanceInterface() {
1423   _impl = NULL;
1424 }
1425 
1426 NetworkPerformanceInterface::~NetworkPerformanceInterface() {
1427   if (_impl != NULL) {
1428     delete _impl;
1429   }
1430 }
1431 
1432 bool NetworkPerformanceInterface::initialize() {
1433   _impl = new NetworkPerformanceInterface::NetworkPerformance();
1434   return _impl != NULL && _impl->initialize();
1435 }
1436 
1437 int NetworkPerformanceInterface::network_utilization(NetworkInterface** network_interfaces) const {
1438   return _impl->network_utilization(network_interfaces);
1439 }
--- EOF ---