1 /*
   2  * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "precompiled.hpp"
  26 #include "logging/log.hpp"
  27 #include "memory/allocation.inline.hpp"
  28 #include "memory/resourceArea.hpp"
  29 #include "pdh_interface.hpp"
  30 #include "runtime/os_perf.hpp"
  31 #include "runtime/os.hpp"
  32 #include "vm_version_ext_x86.hpp"
  33 #include "utilities/macros.hpp"
  34 #include <math.h>
  35 #include <psapi.h>
  36 #include <TlHelp32.h>
  37 
  38 /*
  39  * Windows provides a vast plethora of performance objects and counters,
  40  * consumption of which is assisted using the Performance Data Helper (PDH) interface.
  41  * We import a selected few api entry points from PDH, see pdh_interface.hpp.
  42  *
  43  * The code located in this file is to a large extent an abstraction over much of the
  44  * plumbing needed to start consuming an object and/or counter of choice.
  45  *
  46  */
  47 
  48  /*
  49  * How to use:
  50  * 1. Create query
  51  * 2. Add counters to the query
  52  * 3. Collect the performance data using the query
  53  * 4. Display the performance data using the counters associated with the query
  54  * 5. Destroy query (counter destruction implied)
  55  */
  56 
  57 /*
  58  * Every PDH artifact, like processor, process, thread, memory, and so forth are
  59  * identified with an index that is always the same irrespective
  60  * of the localized version of the operating system or service pack installed.
  61  * INFO: Using PDH APIs Correctly in a Localized Language (Q287159)
  62  *   http://support.microsoft.com/default.aspx?scid=kb;EN-US;q287159
  63  *
  64  * To find the correct index for an object or counter, inspect the registry key / value:
  65  * [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\009\Counter]
  66  *
  67  * some common PDH indexes
  68  */
  69 static const DWORD PDH_PROCESSOR_IDX = 238;
  70 static const DWORD PDH_PROCESSOR_TIME_IDX = 6;
  71 static const DWORD PDH_PRIV_PROCESSOR_TIME_IDX = 144;
  72 static const DWORD PDH_PROCESS_IDX = 230;
  73 static const DWORD PDH_ID_PROCESS_IDX = 784;
  74 static const DWORD PDH_CONTEXT_SWITCH_RATE_IDX = 146;
  75 static const DWORD PDH_SYSTEM_IDX = 2;
  76 
  77 /* useful pdh fmt's */
  78 static const char* const OBJECT_COUNTER_FMT = "\\%s\\%s";
  79 static const size_t OBJECT_COUNTER_FMT_LEN = 2;
  80 static const char* const OBJECT_WITH_INSTANCES_COUNTER_FMT = "\\%s(%s)\\%s";
  81 static const size_t OBJECT_WITH_INSTANCES_COUNTER_FMT_LEN = 4;
  82 static const char* const PROCESS_OBJECT_INSTANCE_COUNTER_FMT = "\\%s(%s#%s)\\%s";
  83 static const size_t PROCESS_OBJECT_INSTANCE_COUNTER_FMT_LEN = 5;
  84 
  85 static const char* process_image_name = NULL; // for example, "java" but could have another image name
  86 static char* pdh_IDProcess_counter_fmt = NULL;   // "\Process(java#%d)\ID Process" */
  87 
  88 // Need to limit how often we update a query to minimize the heisenberg effect.
  89 // (PDH behaves erratically if the counters are queried too often, especially counters that
  90 // store and use values from two consecutive updates, like cpu load.)
  91 static const int min_update_interval_millis = 500;
  92 
  93 /*
  94 * Structs for PDH queries.
  95 */
  96 typedef struct {
  97   HQUERY query;
  98   s8     lastUpdate; // Last time query was updated (current millis).
  99 } UpdateQueryS, *UpdateQueryP;
 100 
 101 
 102 typedef struct {
 103   UpdateQueryS query;
 104   HCOUNTER     counter;
 105   bool         initialized;
 106 } CounterQueryS, *CounterQueryP;
 107 
 108 typedef struct {
 109   UpdateQueryS query;
 110   HCOUNTER*    counters;
 111   int          noOfCounters;
 112   bool         initialized;
 113 } MultiCounterQueryS, *MultiCounterQueryP;
 114 
 115 typedef struct {
 116   MultiCounterQueryP queries;
 117   int                size;
 118   bool               initialized;
 119 } MultiCounterQuerySetS, *MultiCounterQuerySetP;
 120 
 121 typedef struct {
 122   MultiCounterQuerySetS set;
 123   int                   process_index;
 124 } ProcessQueryS, *ProcessQueryP;
 125 
 126 static void pdh_cleanup(HQUERY* const query, HCOUNTER* const counter) {
 127   if (counter != NULL && *counter != NULL) {
 128     PdhDll::PdhRemoveCounter(*counter);
 129     *counter = NULL;
 130   }
 131   if (query != NULL && *query != NULL) {
 132     PdhDll::PdhCloseQuery(*query);
 133     *query = NULL;
 134   }
 135 }
 136 
 137 static CounterQueryP create_counter_query() {
 138   CounterQueryP const query = NEW_C_HEAP_ARRAY(CounterQueryS, 1, mtInternal);
 139   memset(query, 0, sizeof(CounterQueryS));
 140   return query;
 141 }
 142 
 143 static void destroy_counter_query(CounterQueryP query) {
 144   assert(query != NULL, "invariant");
 145   pdh_cleanup(&query->query.query, &query->counter);
 146   FREE_C_HEAP_ARRAY(CounterQueryS, query);
 147 }
 148 
 149 static MultiCounterQueryP create_multi_counter_query() {
 150   MultiCounterQueryP const query = NEW_C_HEAP_ARRAY(MultiCounterQueryS, 1, mtInternal);
 151   memset(query, 0, sizeof(MultiCounterQueryS));
 152   return query;
 153 }
 154 
 155 static void destroy_counter_query(MultiCounterQueryP counter_query) {
 156   if (counter_query != NULL) {
 157     for (int i = 0; i < counter_query->noOfCounters; ++i) {
 158       pdh_cleanup(NULL, &counter_query->counters[i]);
 159     }
 160     FREE_C_HEAP_ARRAY(char, counter_query->counters);
 161     pdh_cleanup(&counter_query->query.query, NULL);
 162     FREE_C_HEAP_ARRAY(MultiCounterQueryS, counter_query);
 163   }
 164 }
 165 
 166 static void destroy_multi_counter_query(MultiCounterQuerySetP counter_query_set) {
 167   for (int i = 0; i < counter_query_set->size; i++) {
 168     for (int j = 0; j < counter_query_set->queries[i].noOfCounters; ++j) {
 169       pdh_cleanup(NULL, &counter_query_set->queries[i].counters[j]);
 170     }
 171     FREE_C_HEAP_ARRAY(char, counter_query_set->queries[i].counters);
 172     pdh_cleanup(&counter_query_set->queries[i].query.query, NULL);
 173   }
 174   FREE_C_HEAP_ARRAY(MultiCounterQueryS, counter_query_set->queries);
 175 }
 176 
 177 static void destroy_counter_query(MultiCounterQuerySetP counter_query_set) {
 178   destroy_multi_counter_query(counter_query_set);
 179   FREE_C_HEAP_ARRAY(MultiCounterQuerySetS, counter_query_set);
 180 }
 181 
 182 static void destroy_counter_query(ProcessQueryP process_query) {
 183   destroy_multi_counter_query(&process_query->set);
 184   FREE_C_HEAP_ARRAY(ProcessQueryS, process_query);
 185 }
 186 
 187 static int open_query(HQUERY* query) {
 188   return PdhDll::PdhOpenQuery(NULL, 0, query);
 189 }
 190 
 191 template <typename QueryP>
 192 static int open_query(QueryP query) {
 193   return open_query(&query->query);
 194 }
 195 
 196 static int allocate_counters(MultiCounterQueryP query, size_t nofCounters) {
 197   assert(query != NULL, "invariant");
 198   assert(!query->initialized, "invariant");
 199   assert(0 == query->noOfCounters, "invariant");
 200   assert(query->counters == NULL, "invariant");
 201   query->counters = (HCOUNTER*)NEW_C_HEAP_ARRAY(char, nofCounters * sizeof(HCOUNTER), mtInternal);
 202   if (query->counters == NULL) {
 203     return OS_ERR;
 204   }
 205   memset(query->counters, 0, nofCounters * sizeof(HCOUNTER));
 206   query->noOfCounters = (int)nofCounters;
 207   return OS_OK;
 208 }
 209 
 210 static int allocate_counters(MultiCounterQuerySetP query_set, size_t nofCounters) {
 211   assert(query_set != NULL, "invariant");
 212   assert(!query_set->initialized, "invariant");
 213   for (int i = 0; i < query_set->size; ++i) {
 214     if (allocate_counters(&query_set->queries[i], nofCounters) != OS_OK) {
 215       return OS_ERR;
 216     }
 217   }
 218   return OS_OK;
 219 }
 220 
 221 static int allocate_counters(ProcessQueryP process_query, size_t nofCounters) {
 222   assert(process_query != NULL, "invariant");
 223   return allocate_counters(&process_query->set, nofCounters);
 224 }
 225 
 226 static void deallocate_counters(MultiCounterQueryP query) {
 227   if (query->counters != NULL) {
 228     FREE_C_HEAP_ARRAY(char, query->counters);
 229     query->counters = NULL;
 230     query->noOfCounters = 0;
 231   }
 232 }
 233 
 234 static OSReturn add_counter(UpdateQueryP query, HCOUNTER* counter, const char* path, bool first_sample_on_init) {
 235   assert(query != NULL, "invariant");
 236   assert(counter != NULL, "invariant");
 237   assert(path != NULL, "invariant");
 238   if (query->query == NULL) {
 239     if (open_query(query) != ERROR_SUCCESS) {
 240       return OS_ERR;
 241     }
 242   }
 243   assert(query->query != NULL, "invariant");
 244   PDH_STATUS status = PdhDll::PdhAddCounter(query->query, path, 0, counter);
 245   if (PDH_CSTATUS_NO_OBJECT == status || PDH_CSTATUS_NO_COUNTER == status) {
 246     return OS_ERR;
 247   }
 248   /*
 249   * According to the MSDN documentation, rate counters must be read twice:
 250   *
 251   * "Obtaining the value of rate counters such as Page faults/sec requires that
 252   *  PdhCollectQueryData be called twice, with a specific time interval between
 253   *  the two calls, before calling PdhGetFormattedCounterValue. Call Sleep to
 254   *  implement the waiting period between the two calls to PdhCollectQueryData."
 255   *
 256   *  Take the first sample here already to allow for the next "real" sample
 257   *  to succeed.
 258   */
 259   if (first_sample_on_init) {
 260     PdhDll::PdhCollectQueryData(query->query);
 261   }
 262   return OS_OK;
 263 }
 264 
 265 template <typename QueryP>
 266 static OSReturn add_counter(QueryP counter_query, HCOUNTER* counter, const char* path, bool first_sample_on_init) {
 267   assert(counter_query != NULL, "invariant");
 268   assert(counter != NULL, "invariant");
 269   assert(path != NULL, "invariant");
 270   return add_counter(&counter_query->query, counter, path, first_sample_on_init);
 271 }
 272 
 273 static OSReturn add_counter(CounterQueryP counter_query, const char* path, bool first_sample_on_init) {
 274   if (add_counter(counter_query, &counter_query->counter, path, first_sample_on_init) != OS_OK) {
 275     // performance counter might be disabled in the registry
 276     return OS_ERR;
 277   }
 278   counter_query->initialized = true;
 279   return OS_OK;
 280 }
 281 
 282 static OSReturn add_process_counter(MultiCounterQueryP query, int slot_index, const char* path, bool first_sample_on_init) {
 283   assert(query != NULL, "invariant");
 284   assert(slot_index < query->noOfCounters, "invariant");
 285   assert(query->counters[slot_index] == NULL, "invariant");
 286   const OSReturn ret = add_counter(query, &query->counters[slot_index], path, first_sample_on_init);
 287   if (OS_OK == ret) {
 288     if (slot_index + 1 == query->noOfCounters) {
 289       query->initialized = true;
 290     }
 291   }
 292   return ret;
 293 }
 294 
 295 static int collect_query_data(UpdateQueryP update_query) {
 296   assert(update_query != NULL, "invariant");
 297   const s8 now = os::javaTimeMillis();
 298   if (now - update_query->lastUpdate > min_update_interval_millis) {
 299     if (PdhDll::PdhCollectQueryData(update_query->query) != ERROR_SUCCESS) {
 300       return OS_ERR;
 301     }
 302     update_query->lastUpdate = now;
 303   }
 304   return OS_OK;
 305 }
 306 
 307 template <typename Query>
 308 static int collect_query_data(Query* counter_query) {
 309   assert(counter_query != NULL, "invariant");
 310   return collect_query_data(&counter_query->query);
 311 }
 312 
 313 static int formatted_counter_value(HCOUNTER counter, DWORD format, PDH_FMT_COUNTERVALUE* const value) {
 314   assert(value != NULL, "invariant");
 315   if (PdhDll::PdhGetFormattedCounterValue(counter, format, NULL, value) != ERROR_SUCCESS) {
 316     return OS_ERR;
 317   }
 318   return OS_OK;
 319 }
 320 
 321 /*
 322 * Working against the Process object and it's related counters is inherently problematic
 323 * when using the PDH API:
 324 *
 325 * Using PDH, a process is not primarily identified by the process id,
 326 * but with a sequential number, for example \Process(java#0), \Process(java#1), ...
 327 * The really bad part is that this list is reset as soon as a process exits:
 328 * If \Process(java#1) exits, \Process(java#3) now becomes \Process(java#2) etc.
 329 *
 330 * The PDH api requires a process identifier to be submitted when registering
 331 * a query, but as soon as the list resets, the query is invalidated (since the name changed).
 332 *
 333 * Solution:
 334 * The #number identifier for a Process query can only decrease after process creation.
 335 *
 336 * We therefore create an array of counter queries for all process object instances
 337 * up to and including ourselves:
 338 *
 339 * Ex. we come in as third process instance (java#2), we then create and register
 340 * queries for the following Process object instances:
 341 * java#0, java#1, java#2
 342 *
 343 * current_query_index_for_process() keeps track of the current "correct" query
 344 * (in order to keep this index valid when the list resets from underneath,
 345 * ensure to call current_query_index_for_process() before every query involving
 346 * Process object instance data).
 347 *
 348 * if unable to query, returns OS_ERR(-1)
 349 */
 350 static int current_query_index_for_process() {
 351   assert(process_image_name != NULL, "invariant");
 352   assert(pdh_IDProcess_counter_fmt != NULL, "invariant");
 353   HQUERY tmpQuery = NULL;
 354   if (open_query(&tmpQuery) != ERROR_SUCCESS) {
 355     return OS_ERR;
 356   }
 357   char counter[512];
 358   HCOUNTER handle_counter = NULL;
 359   // iterate over all instance indexes and try to find our own pid
 360   for (int index = 0; index < max_intx; index++) {
 361     jio_snprintf(counter, sizeof(counter) - 1, pdh_IDProcess_counter_fmt, index);
 362     assert(strlen(counter) < sizeof(counter), "invariant");
 363     if (PdhDll::PdhAddCounter(tmpQuery, counter, 0, &handle_counter) != ERROR_SUCCESS) {
 364       pdh_cleanup(&tmpQuery, &handle_counter);
 365       return OS_ERR;
 366     }
 367     const PDH_STATUS res = PdhDll::PdhCollectQueryData(tmpQuery);
 368     if (res == PDH_INVALID_HANDLE || res == PDH_NO_DATA) {
 369       pdh_cleanup(&tmpQuery, &handle_counter);
 370       return OS_ERR;
 371     } else {
 372       PDH_FMT_COUNTERVALUE counter_value;
 373       formatted_counter_value(handle_counter, PDH_FMT_LONG, &counter_value);
 374       pdh_cleanup(NULL, &handle_counter);
 375       if ((LONG)os::current_process_id() == counter_value.longValue) {
 376         pdh_cleanup(&tmpQuery, NULL);
 377         return index;
 378       }
 379     }
 380   }
 381   pdh_cleanup(&tmpQuery, NULL);
 382   return OS_ERR;
 383 }
 384 
 385 static ProcessQueryP create_process_query() {
 386   ProcessQueryP const process_query = NEW_C_HEAP_ARRAY(ProcessQueryS, 1, mtInternal);
 387   memset(process_query, 0, sizeof(ProcessQueryS));
 388   const int process_index = current_query_index_for_process();
 389   const int current_process_idx = (OS_ERR == process_index) ? 0 : process_index;
 390   process_query->set.queries = NEW_C_HEAP_ARRAY(MultiCounterQueryS, current_process_idx + 1, mtInternal);
 391   memset(process_query->set.queries, 0, sizeof(MultiCounterQueryS) * (current_process_idx + 1));
 392   process_query->process_index = current_process_idx;
 393   process_query->set.size = current_process_idx + 1;
 394   assert(process_query->set.size > process_query->process_index, "invariant");
 395   return process_query;
 396 }
 397 
 398 static MultiCounterQueryP current_process_counter_query(ProcessQueryP process_query) {
 399   assert(process_query != NULL, "invariant");
 400   assert(process_query->process_index < process_query->set.size, "invariant");
 401   return &process_query->set.queries[process_query->process_index];
 402 }
 403 
 404 static void clear_multi_counter(MultiCounterQueryP query) {
 405   for (int i = 0; i < query->noOfCounters; ++i) {
 406     pdh_cleanup(NULL, &query->counters[i]);
 407   }
 408   pdh_cleanup(&query->query.query, NULL);
 409   query->initialized = false;
 410 }
 411 
 412 static int ensure_valid_process_query_index(ProcessQueryP process_query) {
 413   assert(process_query != NULL, "invariant");
 414   const int previous_process_idx = process_query->process_index;
 415   if (previous_process_idx == 0) {
 416     return previous_process_idx;
 417   }
 418   const int current_process_idx = current_query_index_for_process();
 419   if (current_process_idx == previous_process_idx || OS_ERR == current_process_idx ||
 420     current_process_idx >= process_query->set.size) {
 421     return previous_process_idx;
 422   }
 423 
 424   assert(current_process_idx >= 0 && current_process_idx < process_query->set.size, "out of bounds!");
 425   while (current_process_idx < process_query->set.size - 1) {
 426     const int new_size = --process_query->set.size;
 427     clear_multi_counter(&process_query->set.queries[new_size]);
 428   }
 429   assert(current_process_idx < process_query->set.size, "invariant");
 430   process_query->process_index = current_process_idx;
 431   return current_process_idx;
 432 }
 433 
 434 static MultiCounterQueryP current_process_query(ProcessQueryP process_query) {
 435   assert(process_query != NULL, "invariant");
 436   const int current_process_idx = ensure_valid_process_query_index(process_query);
 437   assert(current_process_idx == process_query->process_index, "invariant");
 438   assert(current_process_idx < process_query->set.size, "invariant");
 439   return &process_query->set.queries[current_process_idx];
 440 }
 441 
 442 static int collect_process_query_data(ProcessQueryP process_query) {
 443   assert(process_query != NULL, "invariant");
 444   return collect_query_data(current_process_query(process_query));
 445 }
 446 
 447 static int query_process_counter(ProcessQueryP process_query, int slot_index, DWORD format, PDH_FMT_COUNTERVALUE* const value) {
 448   MultiCounterQueryP const current_query = current_process_counter_query(process_query);
 449   assert(current_query != NULL, "invariant");
 450   assert(slot_index < current_query->noOfCounters, "invariant");
 451   assert(current_query->counters[slot_index] != NULL, "invariant");
 452   return formatted_counter_value(current_query->counters[slot_index], format, value);
 453 }
 454 
 455 /*
 456  * Construct a fully qualified PDH path
 457  *
 458  * @param objectName   a PDH Object string representation(required)
 459  * @param counterName  a PDH Counter string representation(required)
 460  * @param imageName    a process image name string, ex. "java" (opt)
 461  * @param instance     an instance string, ex. "0", "1", ... (opt)
 462  * @return             the fully qualified PDH path.
 463  *
 464  * Caller will need a ResourceMark.
 465  *
 466  * (PdhMakeCounterPath() seems buggy on concatenating instances, hence this function instead)
 467  */
 468 static const char* make_fully_qualified_counter_path(const char* object_name,
 469                                                      const char* counter_name,
 470                                                      const char* image_name = NULL,
 471                                                      const char* instance = NULL) {
 472   assert(object_name != NULL, "invariant");
 473   assert(counter_name != NULL, "invariant");
 474   size_t full_counter_path_len = strlen(object_name) + strlen(counter_name);
 475 
 476   char* full_counter_path;
 477   size_t jio_snprintf_result = 0;
 478   if (image_name) {
 479     /*
 480     * For paths using the "Process" Object.
 481     *
 482     * Examples:
 483     * form:   "\object_name(image_name#instance)\counter_name"
 484     * actual: "\Process(java#2)\ID Process"
 485     */
 486     full_counter_path_len += PROCESS_OBJECT_INSTANCE_COUNTER_FMT_LEN;
 487     full_counter_path_len += strlen(image_name);
 488     /*
 489     * image_name must be passed together with an associated
 490     * instance "number" ("0", "1", "2", ...).
 491     * This is required in order to create valid "Process" Object paths.
 492     *
 493     * Examples: "\Process(java#0)", \Process(java#1"), ...
 494     */
 495     assert(instance != NULL, "invariant");
 496     full_counter_path_len += strlen(instance);
 497     full_counter_path = NEW_RESOURCE_ARRAY_RETURN_NULL(char, full_counter_path_len + 1);
 498     if (full_counter_path == NULL) {
 499       return NULL;
 500     }
 501     jio_snprintf_result = jio_snprintf(full_counter_path,
 502                                        full_counter_path_len + 1,
 503                                        PROCESS_OBJECT_INSTANCE_COUNTER_FMT,
 504                                        object_name,
 505                                        image_name,
 506                                        instance,
 507                                        counter_name);
 508   } else {
 509     if (instance) {
 510       /*
 511       * For paths where the Object has multiple instances.
 512       *
 513       * Examples:
 514       * form:   "\object_name(instance)\counter_name"
 515       * actual: "\Processor(0)\% Privileged Time"
 516       */
 517       full_counter_path_len += strlen(instance);
 518       full_counter_path_len += OBJECT_WITH_INSTANCES_COUNTER_FMT_LEN;
 519     } else {
 520       /*
 521       * For "normal" paths.
 522       *
 523       * Examples:
 524       * form:   "\object_name\counter_name"
 525       * actual: "\Memory\Available Mbytes"
 526       */
 527       full_counter_path_len += OBJECT_COUNTER_FMT_LEN;
 528     }
 529     full_counter_path = NEW_RESOURCE_ARRAY_RETURN_NULL(char, full_counter_path_len + 1);
 530     if (full_counter_path == NULL) {
 531       return NULL;
 532     }
 533     if (instance) {
 534       jio_snprintf_result = jio_snprintf(full_counter_path,
 535                                          full_counter_path_len + 1,
 536                                          OBJECT_WITH_INSTANCES_COUNTER_FMT,
 537                                          object_name,
 538                                          instance,
 539                                          counter_name);
 540     } else {
 541       jio_snprintf_result = jio_snprintf(full_counter_path,
 542                                          full_counter_path_len + 1,
 543                                          OBJECT_COUNTER_FMT,
 544                                          object_name,
 545                                          counter_name);
 546     }
 547   }
 548   assert(full_counter_path_len == jio_snprintf_result, "invariant");
 549   return full_counter_path;
 550 }
 551 
 552 static void log_invalid_pdh_index(DWORD index) {
 553   log_warning(os)("Unable to resolve PDH index: (%ld)", index);
 554   log_warning(os)("Please check the registry if this performance object/counter is disabled");
 555 }
 556 
 557 static bool is_valid_pdh_index(DWORD index) {
 558   DWORD dummy = 0;
 559   if (PdhDll::PdhLookupPerfNameByIndex(NULL, index, NULL, &dummy) != PDH_MORE_DATA) {
 560     log_invalid_pdh_index(index);
 561     return false;
 562   }
 563   return true;
 564 }
 565 
 566 /*
 567  * Maps an index to a resource area allocated string for the localized PDH artifact.
 568  *
 569  * Caller will need a ResourceMark.
 570  *
 571  * @param index    the counter index as specified in the registry
 572  * @param ppBuffer pointer to a char*
 573  * @return         OS_OK if successful, OS_ERR on failure.
 574  */
 575 static OSReturn lookup_name_by_index(DWORD index, char** p_string) {
 576   assert(p_string != NULL, "invariant");
 577   if (!is_valid_pdh_index(index)) {
 578     return OS_ERR;
 579   }
 580   // determine size needed
 581   DWORD size = 0;
 582   PDH_STATUS status = PdhDll::PdhLookupPerfNameByIndex(NULL, index, NULL, &size);
 583   assert(status == PDH_MORE_DATA, "invariant");
 584   *p_string = NEW_RESOURCE_ARRAY_RETURN_NULL(char, size);
 585   if (*p_string== NULL) {
 586     return OS_ERR;
 587   }
 588   if (PdhDll::PdhLookupPerfNameByIndex(NULL, index, *p_string, &size) != ERROR_SUCCESS) {
 589     return OS_ERR;
 590   }
 591   if (0 == size || *p_string == NULL) {
 592     return OS_ERR;
 593   }
 594   // windows vista does not null-terminate the string (although the docs says it will)
 595   (*p_string)[size - 1] = '\0';
 596   return OS_OK;
 597 }
 598 
 599 static const char* copy_string_to_c_heap(const char* string) {
 600   assert(string != NULL, "invariant");
 601   const size_t len = strlen(string);
 602   char* const cheap_allocated_string = NEW_C_HEAP_ARRAY(char, len + 1, mtInternal);
 603   if (NULL == cheap_allocated_string) {
 604     return NULL;
 605   }
 606   strncpy(cheap_allocated_string, string, len + 1);
 607   return cheap_allocated_string;
 608 }
 609 
 610 /*
 611 * Maps an index to a resource area allocated string for the localized PDH artifact.
 612 *
 613 * Caller will need a ResourceMark.
 614 *
 615 * @param index    the counter index as specified in the registry
 616 * @return         localized pdh artifact string if successful, NULL on failure.
 617 */
 618 static const char* pdh_localized_artifact(DWORD pdh_artifact_index) {
 619   char* pdh_localized_artifact_string = NULL;
 620   // get localized name from pdh artifact index
 621   if (lookup_name_by_index(pdh_artifact_index, &pdh_localized_artifact_string) != OS_OK) {
 622     return NULL;
 623   }
 624   return pdh_localized_artifact_string;
 625 }
 626 
 627 /*
 628  * Returns the PDH string identifying the current process image name.
 629  * Use this prefix when getting counters from the PDH process object
 630  * representing your process.
 631  * Ex. "Process(java#0)\Virtual Bytes" - where "java" is the PDH process
 632  * image description.
 633  *
 634  * Caller needs ResourceMark.
 635  *
 636  * @return the process image description. NULL if the call failed.
 637 */
 638 static const char* pdh_process_image_name() {
 639   char* module_name = NEW_RESOURCE_ARRAY_RETURN_NULL(char, MAX_PATH);
 640   if (NULL == module_name) {
 641     return NULL;
 642   }
 643   // Find our module name and use it to extract the image name used by PDH
 644   DWORD getmfn_return = GetModuleFileName(NULL, module_name, MAX_PATH);
 645   if (getmfn_return >= MAX_PATH || 0 == getmfn_return) {
 646     return NULL;
 647   }
 648   if (os::get_last_error() == ERROR_INSUFFICIENT_BUFFER) {
 649     return NULL;
 650   }
 651   char* process_image_name = strrchr(module_name, '\\'); //drop path
 652   process_image_name++;                                  //skip slash
 653   char* dot_pos = strrchr(process_image_name, '.');      //drop .exe
 654   dot_pos[0] = '\0';
 655   return process_image_name;
 656 }
 657 
 658 static void deallocate_pdh_constants() {
 659   if (process_image_name != NULL) {
 660     FREE_C_HEAP_ARRAY(char, process_image_name);
 661     process_image_name = NULL;
 662   }
 663   if (pdh_IDProcess_counter_fmt != NULL) {
 664     FREE_C_HEAP_ARRAY(char, pdh_IDProcess_counter_fmt);
 665     pdh_IDProcess_counter_fmt = NULL;
 666   }
 667 }
 668 
 669 static int allocate_pdh_constants() {
 670   assert(process_image_name == NULL, "invariant");
 671   const char* pdh_image_name = pdh_process_image_name();
 672   if (pdh_image_name == NULL) {
 673     return OS_ERR;
 674   }
 675   process_image_name = copy_string_to_c_heap(pdh_image_name);
 676 
 677   const char* pdh_localized_process_object = pdh_localized_artifact(PDH_PROCESS_IDX);
 678   if (pdh_localized_process_object == NULL) {
 679     return OS_ERR;
 680   }
 681 
 682   const char* pdh_localized_IDProcess_counter = pdh_localized_artifact(PDH_ID_PROCESS_IDX);
 683   if (pdh_localized_IDProcess_counter == NULL) {
 684     return OS_ERR;
 685   }
 686 
 687   size_t pdh_IDProcess_counter_fmt_len = strlen(process_image_name);
 688   pdh_IDProcess_counter_fmt_len += strlen(pdh_localized_process_object);
 689   pdh_IDProcess_counter_fmt_len += strlen(pdh_localized_IDProcess_counter);
 690   pdh_IDProcess_counter_fmt_len += PROCESS_OBJECT_INSTANCE_COUNTER_FMT_LEN;
 691   pdh_IDProcess_counter_fmt_len += 2; // "%d"
 692 
 693   assert(pdh_IDProcess_counter_fmt == NULL, "invariant");
 694   pdh_IDProcess_counter_fmt = NEW_C_HEAP_ARRAY_RETURN_NULL(char, pdh_IDProcess_counter_fmt_len + 1, mtInternal);
 695   if (pdh_IDProcess_counter_fmt == NULL) {
 696     return OS_ERR;
 697   }
 698 
 699   /* "\Process(java#%d)\ID Process" */
 700   const size_t len = jio_snprintf(pdh_IDProcess_counter_fmt,
 701                                   pdh_IDProcess_counter_fmt_len + 1,
 702                                   PROCESS_OBJECT_INSTANCE_COUNTER_FMT,
 703                                   pdh_localized_process_object,
 704                                   process_image_name,
 705                                   "%d",
 706                                   pdh_localized_IDProcess_counter);
 707 
 708   assert(pdh_IDProcess_counter_fmt != NULL, "invariant");
 709   assert(len == pdh_IDProcess_counter_fmt_len, "invariant");
 710   return OS_OK;
 711 }
 712 
 713 /*
 714  * Enuerate the Processor PDH object and returns a buffer containing the enumerated instances.
 715  * Caller needs ResourceMark;
 716  *
 717  * @return  buffer if successful, NULL on failure.
 718 */
 719 static const char* enumerate_cpu_instances() {
 720   char* processor; //'Processor' == PDH_PROCESSOR_IDX
 721   if (lookup_name_by_index(PDH_PROCESSOR_IDX, &processor) != OS_OK) {
 722     return NULL;
 723   }
 724   DWORD c_size = 0;
 725   DWORD i_size = 0;
 726   // enumerate all processors.
 727   PDH_STATUS pdhStat = PdhDll::PdhEnumObjectItems(NULL, // reserved
 728                                                   NULL, // local machine
 729                                                   processor, // object to enumerate
 730                                                   NULL,
 731                                                   &c_size,
 732                                                   NULL, // instance buffer is NULL and
 733                                                   &i_size,  // pass 0 length in order to get the required size
 734                                                   PERF_DETAIL_WIZARD, // counter detail level
 735                                                   0);
 736   if (PdhDll::PdhStatusFail((pdhStat))) {
 737     return NULL;
 738   }
 739   char* const instances = NEW_RESOURCE_ARRAY_RETURN_NULL(char, i_size);
 740   if (instances == NULL) {
 741     return NULL;
 742   }
 743   c_size = 0;
 744   pdhStat = PdhDll::PdhEnumObjectItems(NULL, // reserved
 745                                        NULL, // local machine
 746                                        processor, // object to enumerate
 747                                        NULL,
 748                                        &c_size,
 749                                        instances, // now instance buffer is allocated to be filled in
 750                                        &i_size, // and the required size is known
 751                                        PERF_DETAIL_WIZARD, // counter detail level
 752                                        0);
 753   if (PdhDll::PdhStatusFail((pdhStat))) {
 754     return NULL;
 755   }
 756   return instances;
 757 }
 758 
 759 static int count_logical_cpus(const char* instances) {
 760   assert(instances != NULL, "invariant");
 761   // count logical instances.
 762   DWORD count;
 763   char* tmp;
 764   for (count = 0, tmp = const_cast<char*>(instances); *tmp != '\0'; tmp = &tmp[strlen(tmp) + 1], count++);
 765   // PDH reports an instance for each logical processor plus an instance for the total (_Total)
 766   assert(count == os::processor_count() + 1, "invalid enumeration!");
 767   return count - 1;
 768 }
 769 
 770 static int number_of_logical_cpus() {
 771   static int numberOfCPUS = 0;
 772   if (numberOfCPUS == 0) {
 773     const char* instances = enumerate_cpu_instances();
 774     if (instances == NULL) {
 775       return OS_ERR;
 776     }
 777     numberOfCPUS = count_logical_cpus(instances);
 778   }
 779   return numberOfCPUS;
 780 }
 781 
 782 static double cpu_factor() {
 783   static DWORD  numCpus = 0;
 784   static double cpuFactor = .0;
 785   if (numCpus == 0) {
 786     numCpus = number_of_logical_cpus();
 787     assert(os::processor_count() <= (int)numCpus, "invariant");
 788     cpuFactor = numCpus * 100;
 789   }
 790   return cpuFactor;
 791 }
 792 
 793 static void log_error_message_on_no_PDH_artifact(const char* full_counter_name) {
 794   log_warning(os)("Unable to register PDH query for \"%s\"", full_counter_name);
 795   log_warning(os)("Please check the registry if this performance object/counter is disabled");
 796 }
 797 
 798 static int initialize_cpu_query_counters(MultiCounterQueryP cpu_query, DWORD pdh_counter_idx) {
 799   assert(cpu_query != NULL, "invariant");
 800   assert(cpu_query->counters != NULL, "invariant");
 801   char* processor; //'Processor' == PDH_PROCESSOR_IDX
 802   if (lookup_name_by_index(PDH_PROCESSOR_IDX, &processor) != OS_OK) {
 803     return OS_ERR;
 804   }
 805   char* counter_name = NULL;
 806   if (lookup_name_by_index(pdh_counter_idx, &counter_name) != OS_OK) {
 807     return OS_ERR;
 808   }
 809   if (cpu_query->query.query == NULL) {
 810     if (open_query(cpu_query)) {
 811       return OS_ERR;
 812     }
 813   }
 814   assert(cpu_query->query.query != NULL, "invariant");
 815   size_t counter_len = strlen(processor);
 816   counter_len += strlen(counter_name);
 817   counter_len += OBJECT_WITH_INSTANCES_COUNTER_FMT_LEN; // "\\%s(%s)\\%s"
 818 
 819   DWORD index;
 820   char* tmp;
 821   const char* instances = enumerate_cpu_instances();
 822   for (index = 0, tmp = const_cast<char*>(instances); *tmp != '\0'; tmp = &tmp[strlen(tmp) + 1], index++) {
 823     const size_t tmp_len = strlen(tmp);
 824     char* counter_path = NEW_RESOURCE_ARRAY_RETURN_NULL(char, counter_len + tmp_len + 1);
 825     if (counter_path == NULL) {
 826       return OS_ERR;
 827     }
 828     const size_t jio_snprintf_result = jio_snprintf(counter_path,
 829                                                     counter_len + tmp_len + 1,
 830                                                     OBJECT_WITH_INSTANCES_COUNTER_FMT,
 831                                                     processor,
 832                                                     tmp, // instance "0", "1", .."_Total"
 833                                                     counter_name);
 834     assert(counter_len + tmp_len == jio_snprintf_result, "invariant");
 835     if (add_counter(cpu_query, &cpu_query->counters[index], counter_path, false) != OS_OK) {
 836       // performance counter is disabled in registry and not accessible via PerfLib
 837       log_error_message_on_no_PDH_artifact(counter_path);
 838       // return OS_OK to have the system continue to run without the missing counter
 839       return OS_OK;
 840     }
 841   }
 842   cpu_query->initialized = true;
 843   // Query once to initialize the counters which require at least two samples
 844   // (like the % CPU usage) to calculate correctly.
 845   collect_query_data(cpu_query);
 846   return OS_OK;
 847 }
 848 
 849 static int initialize_cpu_query(MultiCounterQueryP cpu_query, DWORD pdh_counter_idx) {
 850   assert(cpu_query != NULL, "invariant");
 851   assert(!cpu_query->initialized, "invariant");
 852   const int logical_cpu_count = number_of_logical_cpus();
 853   assert(logical_cpu_count >= os::processor_count(), "invariant");
 854   // we also add another counter for instance "_Total"
 855   if (allocate_counters(cpu_query, logical_cpu_count + 1) != OS_OK) {
 856     return OS_ERR;
 857   }
 858   assert(cpu_query->noOfCounters == logical_cpu_count + 1, "invariant");
 859   return initialize_cpu_query_counters(cpu_query, pdh_counter_idx);
 860 }
 861 
 862 static int initialize_process_counter(ProcessQueryP process_query, int slot_index, DWORD pdh_counter_index) {
 863   char* localized_process_object;
 864   if (lookup_name_by_index(PDH_PROCESS_IDX, &localized_process_object) != OS_OK) {
 865     return OS_ERR;
 866   }
 867   assert(localized_process_object != NULL, "invariant");
 868   char* localized_counter_name;
 869   if (lookup_name_by_index(pdh_counter_index, &localized_counter_name) != OS_OK) {
 870     return OS_ERR;
 871   }
 872   assert(localized_counter_name != NULL, "invariant");
 873   for (int i = 0; i < process_query->set.size; ++i) {
 874     char instanceIndexBuffer[32];
 875     const char* counter_path = make_fully_qualified_counter_path(localized_process_object,
 876                                                                  localized_counter_name,
 877                                                                  process_image_name,
 878                                                                  itoa(i, instanceIndexBuffer, 10));
 879     if (counter_path == NULL) {
 880       return OS_ERR;
 881     }
 882     MultiCounterQueryP const query = &process_query->set.queries[i];
 883     if (add_process_counter(query, slot_index, counter_path, true)) {
 884       return OS_ERR;
 885     }
 886   }
 887   return OS_OK;
 888 }
 889 
 890 static CounterQueryP create_counter_query(DWORD pdh_object_idx, DWORD pdh_counter_idx) {
 891   assert(is_valid_pdh_index(pdh_object_idx), "invariant");
 892   assert(is_valid_pdh_index(pdh_counter_idx), "invariant");
 893   CounterQueryP const query = create_counter_query();
 894   const char* object = pdh_localized_artifact(pdh_object_idx);
 895   assert(object != NULL, "invariant");
 896   const char* counter = pdh_localized_artifact(pdh_counter_idx);
 897   assert(counter != NULL, "invariant");
 898   const char* full_counter_path = make_fully_qualified_counter_path(object, counter);
 899   assert(full_counter_path != NULL, "invariant");
 900   add_counter(query, full_counter_path, true);
 901   return query;
 902 }
 903 
 904 static void deallocate() {
 905   deallocate_pdh_constants();
 906   PdhDll::PdhDetach();
 907 }
 908 
 909 static LONG critical_section = 0;
 910 static LONG reference_count = 0;
 911 static bool pdh_initialized = false;
 912 
 913 static void on_initialization_failure() {
 914   // still holder of critical section
 915   deallocate();
 916   InterlockedExchangeAdd(&reference_count, -1);
 917 }
 918 
 919 static OSReturn initialize() {
 920   ResourceMark rm;
 921   if (!PdhDll::PdhAttach()) {
 922     return OS_ERR;
 923   }
 924   if (allocate_pdh_constants() != OS_OK) {
 925     on_initialization_failure();
 926     return OS_ERR;
 927   }
 928   return OS_OK;
 929 }
 930 
 931 /*
 932 * Helper to initialize the PDH library, function pointers, constants and counters.
 933 *
 934 * Reference counting allows for unloading of pdh.dll granted all sessions use the pair:
 935 *
 936 *   pdh_acquire();
 937 *   pdh_release();
 938 *
 939 * @return  OS_OK if successful, OS_ERR on failure.
 940 */
 941 static bool pdh_acquire() {
 942   while (InterlockedCompareExchange(&critical_section, 1, 0) == 1);
 943   InterlockedExchangeAdd(&reference_count, 1);
 944   if (pdh_initialized) {
 945     return true;
 946   }
 947   const OSReturn ret = initialize();
 948   if (OS_OK == ret) {
 949     pdh_initialized = true;
 950   }
 951   while (InterlockedCompareExchange(&critical_section, 0, 1) == 0);
 952   return ret == OS_OK;
 953 }
 954 
 955 static void pdh_release() {
 956   while (InterlockedCompareExchange(&critical_section, 1, 0) == 1);
 957   const LONG prev_ref_count = InterlockedExchangeAdd(&reference_count, -1);
 958   if (1 == prev_ref_count) {
 959     deallocate();
 960     pdh_initialized = false;
 961   }
 962   while (InterlockedCompareExchange(&critical_section, 0, 1) == 0);
 963 }
 964 
 965 class CPUPerformanceInterface::CPUPerformance : public CHeapObj<mtInternal> {
 966   friend class CPUPerformanceInterface;
 967  private:
 968   CounterQueryP _context_switches;
 969   ProcessQueryP _process_cpu_load;
 970   MultiCounterQueryP _machine_cpu_load;
 971 
 972   int cpu_load(int which_logical_cpu, double* cpu_load);
 973   int context_switch_rate(double* rate);
 974   int cpu_load_total_process(double* cpu_load);
 975   int cpu_loads_process(double* jvm_user_load, double* jvm_kernel_load, double* psystemTotalLoad);
 976   CPUPerformance();
 977   ~CPUPerformance();
 978   bool initialize();
 979 };
 980 
 981 class SystemProcessInterface::SystemProcesses : public CHeapObj<mtInternal> {
 982   friend class SystemProcessInterface;
 983  private:
 984   class ProcessIterator : public CHeapObj<mtInternal> {
 985     friend class SystemProcessInterface::SystemProcesses;
 986    private:
 987     HANDLE         _hProcessSnap;
 988     PROCESSENTRY32 _pe32;
 989     BOOL           _valid;
 990     char           _exePath[MAX_PATH];
 991     ProcessIterator();
 992     ~ProcessIterator();
 993     bool initialize();
 994 
 995     int current(SystemProcess* const process_info);
 996     int next_process();
 997     bool is_valid() const { return _valid != FALSE; }
 998     char* allocate_string(const char* str) const;
 999     int snapshot();
1000   };
1001 
1002   ProcessIterator* _iterator;
1003   SystemProcesses();
1004   ~SystemProcesses();
1005   bool initialize();
1006 
1007   // information about system processes
1008   int system_processes(SystemProcess** system_processes, int* no_of_sys_processes) const;
1009 };
1010 
1011 CPUPerformanceInterface::CPUPerformance::CPUPerformance() : _context_switches(NULL), _process_cpu_load(NULL), _machine_cpu_load(NULL) {}
1012 
1013 bool CPUPerformanceInterface::CPUPerformance::initialize() {
1014   if (!pdh_acquire()) {
1015     return false;
1016   }
1017   _context_switches = create_counter_query(PDH_SYSTEM_IDX, PDH_CONTEXT_SWITCH_RATE_IDX);
1018   if (_context_switches == NULL) {
1019     return false;
1020   }
1021   _process_cpu_load = create_process_query();
1022   if (_process_cpu_load == NULL) {
1023     return false;
1024   }
1025   if (allocate_counters(_process_cpu_load, 2) != OS_OK) {
1026     return false;
1027   }
1028   if (initialize_process_counter(_process_cpu_load, 0, PDH_PROCESSOR_TIME_IDX) != OS_OK) {
1029     return false;
1030   }
1031   if (initialize_process_counter(_process_cpu_load, 1, PDH_PRIV_PROCESSOR_TIME_IDX) != OS_OK) {
1032     return false;
1033   }
1034   _process_cpu_load->set.initialized = true;
1035 
1036   _machine_cpu_load = create_multi_counter_query();
1037   if (_machine_cpu_load == NULL) {
1038     return false;
1039   }
1040   if (initialize_cpu_query(_machine_cpu_load, PDH_PROCESSOR_TIME_IDX) != OS_OK) {
1041     return false;
1042   }
1043   return true;
1044 }
1045 
1046 CPUPerformanceInterface::CPUPerformance::~CPUPerformance() {
1047   if (_context_switches != NULL) {
1048     destroy_counter_query(_context_switches);
1049     _context_switches = NULL;
1050   }
1051   if (_process_cpu_load != NULL) {
1052     destroy_counter_query(_process_cpu_load);
1053     _process_cpu_load = NULL;
1054   }
1055   if (_machine_cpu_load != NULL) {
1056     destroy_counter_query(_machine_cpu_load);
1057     _machine_cpu_load = NULL;
1058   }
1059   pdh_release();
1060 }
1061 
1062 CPUPerformanceInterface::CPUPerformanceInterface() {
1063   _impl = NULL;
1064 }
1065 
1066 bool CPUPerformanceInterface::initialize() {
1067   _impl = new CPUPerformanceInterface::CPUPerformance();
1068   return _impl != NULL && _impl->initialize();
1069 }
1070 
1071 CPUPerformanceInterface::~CPUPerformanceInterface() {
1072   if (_impl != NULL) {
1073     delete _impl;
1074   }
1075 }
1076 
1077 int CPUPerformanceInterface::cpu_load(int which_logical_cpu, double* cpu_load) const {
1078   return _impl->cpu_load(which_logical_cpu, cpu_load);
1079 }
1080 
1081 int CPUPerformanceInterface::context_switch_rate(double* rate) const {
1082   return _impl->context_switch_rate(rate);
1083 }
1084 
1085 int CPUPerformanceInterface::cpu_load_total_process(double* cpu_load) const {
1086   return _impl->cpu_load_total_process(cpu_load);
1087 }
1088 
1089 int CPUPerformanceInterface::cpu_loads_process(double* pjvmUserLoad,
1090                                                double* pjvmKernelLoad,
1091                                                double* psystemTotalLoad) const {
1092   return _impl->cpu_loads_process(pjvmUserLoad, pjvmKernelLoad, psystemTotalLoad);
1093 }
1094 
1095 int CPUPerformanceInterface::CPUPerformance::cpu_load(int which_logical_cpu, double* cpu_load) {
1096   assert(_machine_cpu_load != NULL, "invariant");
1097   assert(which_logical_cpu < _machine_cpu_load->noOfCounters, "invariant");
1098   *cpu_load = .0;
1099   if (!_machine_cpu_load->initialized) {
1100     return OS_ERR;
1101   }
1102   if (collect_query_data(_machine_cpu_load)) {
1103     return OS_ERR;
1104   }
1105   // -1 is total (all cpus)
1106   const int counter_idx = -1 == which_logical_cpu ? _machine_cpu_load->noOfCounters - 1 : which_logical_cpu;
1107   PDH_FMT_COUNTERVALUE counter_value;
1108   formatted_counter_value(_machine_cpu_load->counters[counter_idx], PDH_FMT_DOUBLE, &counter_value);
1109   *cpu_load = counter_value.doubleValue / 100;
1110   return OS_OK;
1111 }
1112 
1113 int CPUPerformanceInterface::CPUPerformance::cpu_load_total_process(double* cpu_load) {
1114   assert(_process_cpu_load != NULL, "invariant");
1115   *cpu_load = .0;
1116   if (!_process_cpu_load->set.initialized) {
1117     return OS_ERR;
1118   }
1119   if (collect_process_query_data(_process_cpu_load)) {
1120     return OS_ERR;
1121   }
1122   PDH_FMT_COUNTERVALUE counter_value;
1123   if (query_process_counter(_process_cpu_load, 0, PDH_FMT_DOUBLE | PDH_FMT_NOCAP100, &counter_value) != OS_OK) {
1124     return OS_ERR;
1125   }
1126   double process_load = counter_value.doubleValue / cpu_factor();
1127   process_load = MIN2<double>(1, process_load);
1128   process_load = MAX2<double>(0, process_load);
1129   *cpu_load = process_load;
1130   return OS_OK;
1131 }
1132 
1133 int CPUPerformanceInterface::CPUPerformance::cpu_loads_process(double* pjvmUserLoad,
1134                                                                double* pjvmKernelLoad,
1135                                                                double* psystemTotalLoad) {
1136   assert(pjvmUserLoad != NULL, "pjvmUserLoad is NULL!");
1137   assert(pjvmKernelLoad != NULL, "pjvmKernelLoad is NULL!");
1138   assert(psystemTotalLoad != NULL, "psystemTotalLoad is NULL!");
1139   *pjvmUserLoad = .0;
1140   *pjvmKernelLoad = .0;
1141   *psystemTotalLoad = .0;
1142   if (!_process_cpu_load->set.initialized) {
1143     return OS_ERR;
1144   }
1145   if (collect_process_query_data(_process_cpu_load)) {
1146     return OS_ERR;
1147   }
1148   double process_load = .0;
1149   PDH_FMT_COUNTERVALUE counter_value;
1150   // Read  PDH_PROCESSOR_TIME_IDX
1151   if (query_process_counter(_process_cpu_load, 0, PDH_FMT_DOUBLE | PDH_FMT_NOCAP100, &counter_value) != OS_OK) {
1152     return OS_ERR;
1153   }
1154   process_load = counter_value.doubleValue / cpu_factor();
1155   process_load = MIN2<double>(1, process_load);
1156   process_load = MAX2<double>(0, process_load);
1157   // Read PDH_PRIV_PROCESSOR_TIME_IDX
1158   if (query_process_counter(_process_cpu_load, 1, PDH_FMT_DOUBLE | PDH_FMT_NOCAP100, &counter_value) != OS_OK) {
1159     return OS_ERR;
1160   }
1161   double kernel_load = counter_value.doubleValue / cpu_factor();
1162   kernel_load = MIN2<double>(1, kernel_load);
1163   kernel_load = MAX2<double>(0, kernel_load);
1164   *pjvmKernelLoad = kernel_load;
1165 
1166   double user_load = process_load - kernel_load;
1167   user_load = MIN2<double>(1, user_load);
1168   user_load = MAX2<double>(0, user_load);
1169   *pjvmUserLoad = user_load;
1170 
1171   if (collect_query_data(_machine_cpu_load)) {
1172     return OS_ERR;
1173   }
1174   if (formatted_counter_value(_machine_cpu_load->counters[_machine_cpu_load->noOfCounters - 1], PDH_FMT_DOUBLE, &counter_value) != OS_OK) {
1175     return OS_ERR;
1176   }
1177   double machine_load = counter_value.doubleValue / 100;
1178   assert(machine_load >= 0, "machine_load is negative!");
1179   // clamp at user+system and 1.0
1180   if (*pjvmKernelLoad + *pjvmUserLoad > machine_load) {
1181     machine_load = MIN2(*pjvmKernelLoad + *pjvmUserLoad, 1.0);
1182   }
1183   *psystemTotalLoad = machine_load;
1184   return OS_OK;
1185 }
1186 
1187 int CPUPerformanceInterface::CPUPerformance::context_switch_rate(double* rate) {
1188   assert(rate != NULL, "invariant");
1189   *rate = .0;
1190   if (!_context_switches->initialized) {
1191     return OS_ERR;
1192   }
1193   if (collect_query_data(_context_switches) != OS_OK) {
1194     return OS_ERR;
1195   }
1196   PDH_FMT_COUNTERVALUE counter_value;
1197   if (formatted_counter_value(_context_switches->counter, PDH_FMT_DOUBLE, &counter_value) != OS_OK) {
1198     return OS_ERR;
1199   }
1200   *rate = counter_value.doubleValue;
1201   return OS_OK;
1202 }
1203 
1204 SystemProcessInterface::SystemProcesses::ProcessIterator::ProcessIterator() {
1205   _hProcessSnap = INVALID_HANDLE_VALUE;
1206   _valid = FALSE;
1207   _pe32.dwSize = sizeof(PROCESSENTRY32);
1208 }
1209 
1210 bool SystemProcessInterface::SystemProcesses::ProcessIterator::initialize() {
1211   return true;
1212 }
1213 
1214 int SystemProcessInterface::SystemProcesses::ProcessIterator::snapshot() {
1215   // take snapshot of all process in the system
1216   _hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1217   if (_hProcessSnap == INVALID_HANDLE_VALUE) {
1218     return OS_ERR;
1219   }
1220   // step to first process
1221   _valid = Process32First(_hProcessSnap, &_pe32);
1222   return is_valid() ? OS_OK : OS_ERR;
1223 }
1224 
1225 SystemProcessInterface::SystemProcesses::ProcessIterator::~ProcessIterator() {
1226   if (_hProcessSnap != INVALID_HANDLE_VALUE) {
1227     CloseHandle(_hProcessSnap);
1228   }
1229 }
1230 
1231 int SystemProcessInterface::SystemProcesses::ProcessIterator::current(SystemProcess* process_info) {
1232   assert(is_valid(), "no current process to be fetched!");
1233   assert(process_info != NULL, "process_info is NULL!");
1234   char* exePath = NULL;
1235   HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, _pe32.th32ProcessID);
1236   if (hProcess != NULL) {
1237     HMODULE hMod;
1238     DWORD cbNeeded;
1239     if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded) != 0) {
1240       if (GetModuleFileNameExA(hProcess, hMod, _exePath, sizeof(_exePath)) != 0) {
1241         exePath = _exePath;
1242       }
1243     }
1244     CloseHandle (hProcess);
1245   }
1246   process_info->set_pid((int)_pe32.th32ProcessID);
1247   process_info->set_name(allocate_string(_pe32.szExeFile));
1248   process_info->set_path(allocate_string(exePath));
1249   return OS_OK;
1250 }
1251 
1252 char* SystemProcessInterface::SystemProcesses::ProcessIterator::allocate_string(const char* str) const {
1253   if (str != NULL) {
1254     size_t len = strlen(str);
1255     char* tmp = NEW_C_HEAP_ARRAY(char, len+1, mtInternal);
1256     if (NULL == tmp) {
1257       return NULL;
1258     }
1259     strncpy(tmp, str, len);
1260     tmp[len] = '\0';
1261     return tmp;
1262   }
1263   return NULL;
1264 }
1265 
1266 int SystemProcessInterface::SystemProcesses::ProcessIterator::next_process() {
1267   _valid = Process32Next(_hProcessSnap, &_pe32);
1268   return OS_OK;
1269 }
1270 
1271 SystemProcessInterface::SystemProcesses::SystemProcesses() {
1272   _iterator = NULL;
1273 }
1274 
1275 bool SystemProcessInterface::SystemProcesses::initialize() {
1276   _iterator = new SystemProcessInterface::SystemProcesses::ProcessIterator();
1277   return _iterator != NULL && _iterator->initialize();
1278 }
1279 
1280 SystemProcessInterface::SystemProcesses::~SystemProcesses() {
1281   if (_iterator != NULL) {
1282     delete _iterator;
1283     _iterator = NULL;
1284   }
1285 }
1286 
1287 int SystemProcessInterface::SystemProcesses::system_processes(SystemProcess** system_processes,
1288                                                               int* no_of_sys_processes) const {
1289   assert(system_processes != NULL, "system_processes pointer is NULL!");
1290   assert(no_of_sys_processes != NULL, "system_processes counter pointers is NULL!");
1291   assert(_iterator != NULL, "iterator is NULL!");
1292 
1293   // initialize pointers
1294   *no_of_sys_processes = 0;
1295   *system_processes = NULL;
1296 
1297   // take process snapshot
1298   if (_iterator->snapshot() != OS_OK) {
1299     return OS_ERR;
1300   }
1301 
1302   while (_iterator->is_valid()) {
1303     SystemProcess* tmp = new SystemProcess();
1304     _iterator->current(tmp);
1305 
1306     //if already existing head
1307     if (*system_processes != NULL) {
1308       //move "first to second"
1309       tmp->set_next(*system_processes);
1310     }
1311     // new head
1312     *system_processes = tmp;
1313     // increment
1314     (*no_of_sys_processes)++;
1315     // step forward
1316     _iterator->next_process();
1317   }
1318   return OS_OK;
1319 }
1320 
1321 int SystemProcessInterface::system_processes(SystemProcess** system_procs,
1322                                              int* no_of_sys_processes) const {
1323   return _impl->system_processes(system_procs, no_of_sys_processes);
1324 }
1325 
1326 SystemProcessInterface::SystemProcessInterface() {
1327   _impl = NULL;
1328 }
1329 
1330 bool SystemProcessInterface::initialize() {
1331   _impl = new SystemProcessInterface::SystemProcesses();
1332   return _impl != NULL && _impl->initialize();
1333 }
1334 
1335 SystemProcessInterface::~SystemProcessInterface() {
1336   if (_impl != NULL) {
1337     delete _impl;
1338   }
1339 }
1340 
1341 CPUInformationInterface::CPUInformationInterface() {
1342   _cpu_info = NULL;
1343 }
1344 
1345 bool CPUInformationInterface::initialize() {
1346   _cpu_info = new CPUInformation();
1347   if (NULL == _cpu_info) {
1348     return false;
1349   }
1350   _cpu_info->set_number_of_hardware_threads(VM_Version_Ext::number_of_threads());
1351   _cpu_info->set_number_of_cores(VM_Version_Ext::number_of_cores());
1352   _cpu_info->set_number_of_sockets(VM_Version_Ext::number_of_sockets());
1353   _cpu_info->set_cpu_name(VM_Version_Ext::cpu_name());
1354   _cpu_info->set_cpu_description(VM_Version_Ext::cpu_description());
1355   return true;
1356 }
1357 
1358 CPUInformationInterface::~CPUInformationInterface() {
1359   if (_cpu_info != NULL) {
1360     const char* cpu_name = _cpu_info->cpu_name();
1361     if (cpu_name != NULL) {
1362       FREE_C_HEAP_ARRAY(char, cpu_name);
1363       _cpu_info->set_cpu_name(NULL);
1364     }
1365     const char* cpu_desc = _cpu_info->cpu_description();
1366     if (cpu_desc != NULL) {
1367       FREE_C_HEAP_ARRAY(char, cpu_desc);
1368       _cpu_info->set_cpu_description(NULL);
1369     }
1370     delete _cpu_info;
1371     _cpu_info = NULL;
1372   }
1373 }
1374 
1375 int CPUInformationInterface::cpu_information(CPUInformation& cpu_info) {
1376   if (NULL == _cpu_info) {
1377     return OS_ERR;
1378   }
1379   cpu_info = *_cpu_info; // shallow copy assignment
1380   return OS_OK;
1381 }