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 "iphlp_interface.hpp"
  26 #include "memory/allocation.inline.hpp"
  27 #include "memory/resourceArea.hpp"
  28 #include "pdh_interface.hpp"
  29 #include "runtime/os_perf.hpp"
  30 #include "runtime/os.hpp"
  31 #include "utilities/macros.hpp"
  32 #include "vm_version_ext_x86.hpp"
  33 #include <math.h>
  34 #include <psapi.h>
  35 #include <TlHelp32.h>
  36 
  37 /*
  38  * Windows provides a vast plethora of performance objects and counters,
  39  * consumption of which is assisted using the Performance Data Helper (PDH) interface.
  40  * We import a selected few api entry points from PDH, see pdh_interface.hpp.
  41  *
  42  * The code located in this file is to a large extent an abstraction over much of the
  43  * plumbing needed to start consuming an object and/or counter of choice.
  44  *
  45  */
  46 
  47  /*
  48  * How to use:
  49  * 1. Create query
  50  * 2. Add counters to the query
  51  * 3. Collect the performance data using the query
  52  * 4. Display the performance data using the counters associated with the query
  53  * 5. Destroy query (counter destruction implied)
  54  */
  55 
  56 /*
  57  * Every PDH artifact, like processor, process, thread, memory, and so forth are
  58  * identified with an index that is always the same irrespective
  59  * of the localized version of the operating system or service pack installed.
  60  * INFO: Using PDH APIs Correctly in a Localized Language (Q287159)
  61  *   http://support.microsoft.com/default.aspx?scid=kb;EN-US;q287159
  62  *
  63  * To find the correct index for an object or counter, inspect the registry key / value:
  64  * [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\009\Counter]
  65  *
  66  * some common PDH indexes
  67  */
  68 static const DWORD PDH_PROCESSOR_IDX = 238;
  69 static const DWORD PDH_PROCESSOR_TIME_IDX = 6;
  70 static const DWORD PDH_PRIV_PROCESSOR_TIME_IDX = 144;
  71 static const DWORD PDH_PROCESS_IDX = 230;
  72 static const DWORD PDH_ID_PROCESS_IDX = 784;
  73 static const DWORD PDH_CONTEXT_SWITCH_RATE_IDX = 146;
  74 static const DWORD PDH_SYSTEM_IDX = 2;
  75 
  76 /* useful pdh fmt's */
  77 static const char* const OBJECT_COUNTER_FMT = "\\%s\\%s";
  78 static const size_t OBJECT_COUNTER_FMT_LEN = 2;
  79 static const char* const OBJECT_WITH_INSTANCES_COUNTER_FMT = "\\%s(%s)\\%s";
  80 static const size_t OBJECT_WITH_INSTANCES_COUNTER_FMT_LEN = 4;
  81 static const char* const PROCESS_OBJECT_INSTANCE_COUNTER_FMT = "\\%s(%s#%s)\\%s";
  82 static const size_t PROCESS_OBJECT_INSTANCE_COUNTER_FMT_LEN = 5;
  83 
  84 static const char* process_image_name = NULL; // for example, "java" but could have another image name
  85 static char* pdh_IDProcess_counter_fmt = NULL;   // "\Process(java#%d)\ID Process" */
  86 
  87 // Need to limit how often we update a query to minimize the heisenberg effect.
  88 // (PDH behaves erratically if the counters are queried too often, especially counters that
  89 // store and use values from two consecutive updates, like cpu load.)
  90 static const int min_update_interval_millis = 500;
  91 
  92 /*
  93 * Structs for PDH queries.
  94 */
  95 typedef struct {
  96   HQUERY query;
  97   s8     lastUpdate; // Last time query was updated (current millis).
  98 } UpdateQueryS, *UpdateQueryP;
  99 
 100 
 101 typedef struct {
 102   UpdateQueryS query;
 103   HCOUNTER     counter;
 104   bool         initialized;
 105 } CounterQueryS, *CounterQueryP;
 106 
 107 typedef struct {
 108   UpdateQueryS query;
 109   HCOUNTER*    counters;
 110   int          noOfCounters;
 111   bool         initialized;
 112 } MultiCounterQueryS, *MultiCounterQueryP;
 113 
 114 typedef struct {
 115   MultiCounterQueryP queries;
 116   int                size;
 117   bool               initialized;
 118 } MultiCounterQuerySetS, *MultiCounterQuerySetP;
 119 
 120 typedef struct {
 121   MultiCounterQuerySetS set;
 122   int                   process_index;
 123 } ProcessQueryS, *ProcessQueryP;
 124 
 125 static void pdh_cleanup(HQUERY* const query, HCOUNTER* const counter) {
 126   if (counter != NULL && *counter != NULL) {
 127     PdhDll::PdhRemoveCounter(*counter);
 128     *counter = NULL;
 129   }
 130   if (query != NULL && *query != NULL) {
 131     PdhDll::PdhCloseQuery(*query);
 132     *query = NULL;
 133   }
 134 }
 135 
 136 static CounterQueryP create_counter_query() {
 137   CounterQueryP const query = NEW_C_HEAP_ARRAY(CounterQueryS, 1, mtInternal);
 138   memset(query, 0, sizeof(CounterQueryS));
 139   return query;
 140 }
 141 
 142 static void destroy_counter_query(CounterQueryP query) {
 143   assert(query != NULL, "invariant");
 144   pdh_cleanup(&query->query.query, &query->counter);
 145   FREE_C_HEAP_ARRAY(CounterQueryS, query, mtInternal);
 146 }
 147 
 148 static MultiCounterQueryP create_multi_counter_query() {
 149   MultiCounterQueryP const query = NEW_C_HEAP_ARRAY(MultiCounterQueryS, 1, mtInternal);
 150   memset(query, 0, sizeof(MultiCounterQueryS));
 151   return query;
 152 }
 153 
 154 static void destroy_counter_query(MultiCounterQueryP counter_query) {
 155   if (counter_query != NULL) {
 156     for (int i = 0; i < counter_query->noOfCounters; ++i) {
 157       pdh_cleanup(NULL, &counter_query->counters[i]);
 158     }
 159     FREE_C_HEAP_ARRAY(char, counter_query->counters, mtInternal);
 160     pdh_cleanup(&counter_query->query.query, NULL);
 161     FREE_C_HEAP_ARRAY(MultiCounterQueryS, counter_query, mtInternal);
 162   }
 163 }
 164 
 165 static void destroy_multi_counter_query(MultiCounterQuerySetP counter_query_set) {
 166   for (int i = 0; i < counter_query_set->size; i++) {
 167     for (int j = 0; j < counter_query_set->queries[i].noOfCounters; ++j) {
 168       pdh_cleanup(NULL, &counter_query_set->queries[i].counters[j]);
 169     }
 170     FREE_C_HEAP_ARRAY(char, counter_query_set->queries[i].counters, mtInternal);
 171     pdh_cleanup(&counter_query_set->queries[i].query.query, NULL);
 172   }
 173   FREE_C_HEAP_ARRAY(MultiCounterQueryS, counter_query_set->queries, mtInternal);
 174 }
 175 
 176 static void destroy_counter_query(MultiCounterQuerySetP counter_query_set) {
 177   destroy_multi_counter_query(counter_query_set);
 178   FREE_C_HEAP_ARRAY(MultiCounterQuerySetS, counter_query_set, mtInternal);
 179 }
 180 
 181 static void destroy_counter_query(ProcessQueryP process_query) {
 182   destroy_multi_counter_query(&process_query->set);
 183   FREE_C_HEAP_ARRAY(ProcessQueryS, process_query, mtInternal);
 184 }
 185 
 186 static int open_query(HQUERY* query) {
 187   return PdhDll::PdhOpenQuery(NULL, 0, query);
 188 }
 189 
 190 template <typename QueryP>
 191 static int open_query(QueryP query) {
 192   return open_query(&query->query);
 193 }
 194 
 195 static int allocate_counters(MultiCounterQueryP query, size_t nofCounters) {
 196   assert(query != NULL, "invariant");
 197   assert(!query->initialized, "invariant");
 198   assert(0 == query->noOfCounters, "invariant");
 199   assert(query->counters == NULL, "invariant");
 200   query->counters = (HCOUNTER*)NEW_C_HEAP_ARRAY(char, nofCounters * sizeof(HCOUNTER), mtInternal);
 201   if (query->counters == NULL) {
 202     return OS_ERR;
 203   }
 204   memset(query->counters, 0, nofCounters * sizeof(HCOUNTER));
 205   query->noOfCounters = (int)nofCounters;
 206   return OS_OK;
 207 }
 208 
 209 static int allocate_counters(MultiCounterQuerySetP query_set, size_t nofCounters) {
 210   assert(query_set != NULL, "invariant");
 211   assert(!query_set->initialized, "invariant");
 212   for (int i = 0; i < query_set->size; ++i) {
 213     if (allocate_counters(&query_set->queries[i], nofCounters) != OS_OK) {
 214       return OS_ERR;
 215     }
 216   }
 217   return OS_OK;
 218 }
 219 
 220 static int allocate_counters(ProcessQueryP process_query, size_t nofCounters) {
 221   assert(process_query != NULL, "invariant");
 222   return allocate_counters(&process_query->set, nofCounters);
 223 }
 224 
 225 static void deallocate_counters(MultiCounterQueryP query) {
 226   if (query->counters != NULL) {
 227     FREE_C_HEAP_ARRAY(char, query->counters, mtInternal);
 228     query->counters = NULL;
 229     query->noOfCounters = 0;
 230   }
 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_ARRAY(ProcessQueryS, 1, 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   if (LogJFR) tty->print_cr("Unable to resolve PDH index: (%ld)", index);
 555   if (LogJFR) tty->print_cr("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   if (process_image_name != NULL) {
 661     FREE_C_HEAP_ARRAY(char, process_image_name, mtInternal);
 662     process_image_name = NULL;
 663   }
 664   if (pdh_IDProcess_counter_fmt != NULL) {
 665     FREE_C_HEAP_ARRAY(char, pdh_IDProcess_counter_fmt, mtInternal);
 666     pdh_IDProcess_counter_fmt = NULL;
 667   }
 668 }
 669 
 670 static int allocate_pdh_constants() {
 671   assert(process_image_name == NULL, "invariant");
 672   const char* pdh_image_name = pdh_process_image_name();
 673   if (pdh_image_name == NULL) {
 674     return OS_ERR;
 675   }
 676   process_image_name = copy_string_to_c_heap(pdh_image_name);
 677 
 678   const char* pdh_localized_process_object = pdh_localized_artifact(PDH_PROCESS_IDX);
 679   if (pdh_localized_process_object == NULL) {
 680     return OS_ERR;
 681   }
 682 
 683   const char* pdh_localized_IDProcess_counter = pdh_localized_artifact(PDH_ID_PROCESS_IDX);
 684   if (pdh_localized_IDProcess_counter == NULL) {
 685     return OS_ERR;
 686   }
 687 
 688   size_t pdh_IDProcess_counter_fmt_len = strlen(process_image_name);
 689   pdh_IDProcess_counter_fmt_len += strlen(pdh_localized_process_object);
 690   pdh_IDProcess_counter_fmt_len += strlen(pdh_localized_IDProcess_counter);
 691   pdh_IDProcess_counter_fmt_len += PROCESS_OBJECT_INSTANCE_COUNTER_FMT_LEN;
 692   pdh_IDProcess_counter_fmt_len += 2; // "%d"
 693 
 694   assert(pdh_IDProcess_counter_fmt == NULL, "invariant");
 695   pdh_IDProcess_counter_fmt = NEW_C_HEAP_ARRAY_RETURN_NULL(char, pdh_IDProcess_counter_fmt_len + 1, mtInternal);
 696   if (pdh_IDProcess_counter_fmt == NULL) {
 697     return OS_ERR;
 698   }
 699 
 700   /* "\Process(java#%d)\ID Process" */
 701   const size_t len = jio_snprintf(pdh_IDProcess_counter_fmt,
 702                                   pdh_IDProcess_counter_fmt_len + 1,
 703                                   PROCESS_OBJECT_INSTANCE_COUNTER_FMT,
 704                                   pdh_localized_process_object,
 705                                   process_image_name,
 706                                   "%d",
 707                                   pdh_localized_IDProcess_counter);
 708 
 709   assert(pdh_IDProcess_counter_fmt != NULL, "invariant");
 710   assert(len == pdh_IDProcess_counter_fmt_len, "invariant");
 711   return OS_OK;
 712 }
 713 
 714 /*
 715  * Enuerate the Processor PDH object and returns a buffer containing the enumerated instances.
 716  * Caller needs ResourceMark;
 717  *
 718  * @return  buffer if successful, NULL on failure.
 719 */
 720 static const char* enumerate_cpu_instances() {
 721   char* processor; //'Processor' == PDH_PROCESSOR_IDX
 722   if (lookup_name_by_index(PDH_PROCESSOR_IDX, &processor) != OS_OK) {
 723     return NULL;
 724   }
 725   DWORD c_size = 0;
 726   DWORD i_size = 0;
 727   // enumerate all processors.
 728   PDH_STATUS pdhStat = PdhDll::PdhEnumObjectItems(NULL, // reserved
 729                                                   NULL, // local machine
 730                                                   processor, // object to enumerate
 731                                                   NULL,
 732                                                   &c_size,
 733                                                   NULL, // instance buffer is NULL and
 734                                                   &i_size,  // pass 0 length in order to get the required size
 735                                                   PERF_DETAIL_WIZARD, // counter detail level
 736                                                   0);
 737   if (PdhDll::PdhStatusFail((pdhStat))) {
 738     return NULL;
 739   }
 740   char* const instances = NEW_RESOURCE_ARRAY_RETURN_NULL(char, i_size);
 741   if (instances == NULL) {
 742     return NULL;
 743   }
 744   c_size = 0;
 745   pdhStat = PdhDll::PdhEnumObjectItems(NULL, // reserved
 746                                        NULL, // local machine
 747                                        processor, // object to enumerate
 748                                        NULL,
 749                                        &c_size,
 750                                        instances, // now instance buffer is allocated to be filled in
 751                                        &i_size, // and the required size is known
 752                                        PERF_DETAIL_WIZARD, // counter detail level
 753                                        0);
 754   if (PdhDll::PdhStatusFail((pdhStat))) {
 755     return NULL;
 756   }
 757   return instances;
 758 }
 759 
 760 static int count_logical_cpus(const char* instances) {
 761   assert(instances != NULL, "invariant");
 762   // count logical instances.
 763   DWORD count;
 764   char* tmp;
 765   for (count = 0, tmp = const_cast<char*>(instances); *tmp != '\0'; tmp = &tmp[strlen(tmp) + 1], count++);
 766   // PDH reports an instance for each logical processor plus an instance for the total (_Total)
 767   assert(count == os::processor_count() + 1, "invalid enumeration!");
 768   return count - 1;
 769 }
 770 
 771 static int number_of_logical_cpus() {
 772   static int numberOfCPUS = 0;
 773   if (numberOfCPUS == 0) {
 774     const char* instances = enumerate_cpu_instances();
 775     if (instances == NULL) {
 776       return OS_ERR;
 777     }
 778     numberOfCPUS = count_logical_cpus(instances);
 779   }
 780   return numberOfCPUS;
 781 }
 782 
 783 static double cpu_factor() {
 784   static DWORD  numCpus = 0;
 785   static double cpuFactor = .0;
 786   if (numCpus == 0) {
 787     numCpus = number_of_logical_cpus();
 788     assert(os::processor_count() <= (int)numCpus, "invariant");
 789     cpuFactor = numCpus * 100;
 790   }
 791   return cpuFactor;
 792 }
 793 
 794 static void log_error_message_on_no_PDH_artifact(const char* full_counter_name) {
 795   if (LogJFR) tty->print_cr("Unable to register PDH query for \"%s\"", full_counter_name);
 796   if (LogJFR) tty->print_cr("Please check the registry if this performance object/counter is disabled");
 797 }
 798 
 799 static int initialize_cpu_query_counters(MultiCounterQueryP cpu_query, DWORD pdh_counter_idx) {
 800   assert(cpu_query != NULL, "invariant");
 801   assert(cpu_query->counters != NULL, "invariant");
 802   char* processor; //'Processor' == PDH_PROCESSOR_IDX
 803   if (lookup_name_by_index(PDH_PROCESSOR_IDX, &processor) != OS_OK) {
 804     return OS_ERR;
 805   }
 806   char* counter_name = NULL;
 807   if (lookup_name_by_index(pdh_counter_idx, &counter_name) != OS_OK) {
 808     return OS_ERR;
 809   }
 810   if (cpu_query->query.query == NULL) {
 811     if (open_query(cpu_query)) {
 812       return OS_ERR;
 813     }
 814   }
 815   assert(cpu_query->query.query != NULL, "invariant");
 816   size_t counter_len = strlen(processor);
 817   counter_len += strlen(counter_name);
 818   counter_len += OBJECT_WITH_INSTANCES_COUNTER_FMT_LEN; // "\\%s(%s)\\%s"
 819 
 820   DWORD index;
 821   char* tmp;
 822   const char* instances = enumerate_cpu_instances();
 823   for (index = 0, tmp = const_cast<char*>(instances); *tmp != '\0'; tmp = &tmp[strlen(tmp) + 1], index++) {
 824     const size_t tmp_len = strlen(tmp);
 825     char* counter_path = NEW_RESOURCE_ARRAY_RETURN_NULL(char, counter_len + tmp_len + 1);
 826     if (counter_path == NULL) {
 827       return OS_ERR;
 828     }
 829     const size_t jio_snprintf_result = jio_snprintf(counter_path,
 830                                                     counter_len + tmp_len + 1,
 831                                                     OBJECT_WITH_INSTANCES_COUNTER_FMT,
 832                                                     processor,
 833                                                     tmp, // instance "0", "1", .."_Total"
 834                                                     counter_name);
 835     assert(counter_len + tmp_len == jio_snprintf_result, "invariant");
 836     if (add_counter(cpu_query, &cpu_query->counters[index], counter_path, false) != OS_OK) {
 837       // performance counter is disabled in registry and not accessible via PerfLib
 838       log_error_message_on_no_PDH_artifact(counter_path);
 839       // return OS_OK to have the system continue to run without the missing counter
 840       return OS_OK;
 841     }
 842   }
 843   cpu_query->initialized = true;
 844   // Query once to initialize the counters which require at least two samples
 845   // (like the % CPU usage) to calculate correctly.
 846   collect_query_data(cpu_query);
 847   return OS_OK;
 848 }
 849 
 850 static int initialize_cpu_query(MultiCounterQueryP cpu_query, DWORD pdh_counter_idx) {
 851   assert(cpu_query != NULL, "invariant");
 852   assert(!cpu_query->initialized, "invariant");
 853   const int logical_cpu_count = number_of_logical_cpus();
 854   assert(logical_cpu_count >= os::processor_count(), "invariant");
 855   // we also add another counter for instance "_Total"
 856   if (allocate_counters(cpu_query, logical_cpu_count + 1) != OS_OK) {
 857     return OS_ERR;
 858   }
 859   assert(cpu_query->noOfCounters == logical_cpu_count + 1, "invariant");
 860   return initialize_cpu_query_counters(cpu_query, pdh_counter_idx);
 861 }
 862 
 863 static int initialize_process_counter(ProcessQueryP process_query, int slot_index, DWORD pdh_counter_index) {
 864   char* localized_process_object;
 865   if (lookup_name_by_index(PDH_PROCESS_IDX, &localized_process_object) != OS_OK) {
 866     return OS_ERR;
 867   }
 868   assert(localized_process_object != NULL, "invariant");
 869   char* localized_counter_name;
 870   if (lookup_name_by_index(pdh_counter_index, &localized_counter_name) != OS_OK) {
 871     return OS_ERR;
 872   }
 873   assert(localized_counter_name != NULL, "invariant");
 874   for (int i = 0; i < process_query->set.size; ++i) {
 875     char instanceIndexBuffer[32];
 876     const char* counter_path = make_fully_qualified_counter_path(localized_process_object,
 877                                                                  localized_counter_name,
 878                                                                  process_image_name,
 879                                                                  itoa(i, instanceIndexBuffer, 10));
 880     if (counter_path == NULL) {
 881       return OS_ERR;
 882     }
 883     MultiCounterQueryP const query = &process_query->set.queries[i];
 884     if (add_process_counter(query, slot_index, counter_path, true)) {
 885       return OS_ERR;
 886     }
 887   }
 888   return OS_OK;
 889 }
 890 
 891 static CounterQueryP create_counter_query(DWORD pdh_object_idx, DWORD pdh_counter_idx) {
 892   if (!((is_valid_pdh_index(pdh_object_idx) && is_valid_pdh_index(pdh_counter_idx)))) {
 893     return NULL;
 894   }
 895   CounterQueryP const query = create_counter_query();
 896   const char* object = pdh_localized_artifact(pdh_object_idx);
 897   assert(object != NULL, "invariant");
 898   const char* counter = pdh_localized_artifact(pdh_counter_idx);
 899   assert(counter != NULL, "invariant");
 900   const char* full_counter_path = make_fully_qualified_counter_path(object, counter);
 901   assert(full_counter_path != NULL, "invariant");
 902   add_counter(query, full_counter_path, true);
 903   return query;
 904 }
 905 
 906 static void deallocate() {
 907   deallocate_pdh_constants();
 908   PdhDll::PdhDetach();
 909 }
 910 
 911 static LONG critical_section = 0;
 912 static LONG reference_count = 0;
 913 static bool pdh_initialized = false;
 914 
 915 static void on_initialization_failure() {
 916   // still holder of critical section
 917   deallocate();
 918   InterlockedExchangeAdd(&reference_count, -1);
 919 }
 920 
 921 static OSReturn initialize() {
 922   ResourceMark rm;
 923   if (!PdhDll::PdhAttach()) {
 924     return OS_ERR;
 925   }
 926   if (allocate_pdh_constants() != OS_OK) {
 927     on_initialization_failure();
 928     return OS_ERR;
 929   }
 930   return OS_OK;
 931 }
 932 
 933 /*
 934 * Helper to initialize the PDH library, function pointers, constants and counters.
 935 *
 936 * Reference counting allows for unloading of pdh.dll granted all sessions use the pair:
 937 *
 938 *   pdh_acquire();
 939 *   pdh_release();
 940 *
 941 * @return  OS_OK if successful, OS_ERR on failure.
 942 */
 943 static bool pdh_acquire() {
 944   while (InterlockedCompareExchange(&critical_section, 1, 0) == 1);
 945   InterlockedExchangeAdd(&reference_count, 1);
 946   if (pdh_initialized) {
 947     return true;
 948   }
 949   const OSReturn ret = initialize();
 950   if (OS_OK == ret) {
 951     pdh_initialized = true;
 952   }
 953   while (InterlockedCompareExchange(&critical_section, 0, 1) == 0);
 954   return ret == OS_OK;
 955 }
 956 
 957 static void pdh_release() {
 958   while (InterlockedCompareExchange(&critical_section, 1, 0) == 1);
 959   const LONG prev_ref_count = InterlockedExchangeAdd(&reference_count, -1);
 960   if (1 == prev_ref_count) {
 961     deallocate();
 962     pdh_initialized = false;
 963   }
 964   while (InterlockedCompareExchange(&critical_section, 0, 1) == 0);
 965 }
 966 
 967 class CPUPerformanceInterface::CPUPerformance : public CHeapObj<mtInternal> {
 968   friend class CPUPerformanceInterface;
 969  private:
 970   CounterQueryP _context_switches;
 971   ProcessQueryP _process_cpu_load;
 972   MultiCounterQueryP _machine_cpu_load;
 973 
 974   int cpu_load(int which_logical_cpu, double* cpu_load);
 975   int context_switch_rate(double* rate);
 976   int cpu_load_total_process(double* cpu_load);
 977   int cpu_loads_process(double* jvm_user_load, double* jvm_kernel_load, double* psystemTotalLoad);
 978   CPUPerformance();
 979   ~CPUPerformance();
 980   bool initialize();
 981 };
 982 
 983 class SystemProcessInterface::SystemProcesses : public CHeapObj<mtInternal> {
 984   friend class SystemProcessInterface;
 985  private:
 986   class ProcessIterator : public CHeapObj<mtInternal> {
 987     friend class SystemProcessInterface::SystemProcesses;
 988    private:
 989     HANDLE         _hProcessSnap;
 990     PROCESSENTRY32 _pe32;
 991     BOOL           _valid;
 992     char           _exePath[MAX_PATH];
 993     ProcessIterator();
 994     ~ProcessIterator();
 995     bool initialize();
 996 
 997     int current(SystemProcess* const process_info);
 998     int next_process();
 999     bool is_valid() const { return _valid != FALSE; }
1000     char* allocate_string(const char* str) const;
1001     int snapshot();
1002   };
1003 
1004   ProcessIterator* _iterator;
1005   SystemProcesses();
1006   ~SystemProcesses();
1007   bool initialize();
1008 
1009   // information about system processes
1010   int system_processes(SystemProcess** system_processes, int* no_of_sys_processes) const;
1011 };
1012 
1013 CPUPerformanceInterface::CPUPerformance::CPUPerformance() : _context_switches(NULL), _process_cpu_load(NULL), _machine_cpu_load(NULL) {}
1014 
1015 bool CPUPerformanceInterface::CPUPerformance::initialize() {
1016   if (!pdh_acquire()) {
1017     return true;
1018   }
1019   _context_switches = create_counter_query(PDH_SYSTEM_IDX, PDH_CONTEXT_SWITCH_RATE_IDX);
1020   _process_cpu_load = create_process_query();
1021   if (_process_cpu_load == NULL) {
1022     return true;
1023   }
1024   if (allocate_counters(_process_cpu_load, 2) != OS_OK) {
1025     return true;
1026   }
1027   if (initialize_process_counter(_process_cpu_load, 0, PDH_PROCESSOR_TIME_IDX) != OS_OK) {
1028     return true;
1029   }
1030   if (initialize_process_counter(_process_cpu_load, 1, PDH_PRIV_PROCESSOR_TIME_IDX) != OS_OK) {
1031     return true;
1032   }
1033   _process_cpu_load->set.initialized = true;
1034   _machine_cpu_load = create_multi_counter_query();
1035   if (_machine_cpu_load == NULL) {
1036     return true;
1037   }
1038   initialize_cpu_query(_machine_cpu_load, PDH_PROCESSOR_TIME_IDX);
1039   return true;
1040 }
1041 
1042 CPUPerformanceInterface::CPUPerformance::~CPUPerformance() {
1043   if (_context_switches != NULL) {
1044     destroy_counter_query(_context_switches);
1045     _context_switches = NULL;
1046   }
1047   if (_process_cpu_load != NULL) {
1048     destroy_counter_query(_process_cpu_load);
1049     _process_cpu_load = NULL;
1050   }
1051   if (_machine_cpu_load != NULL) {
1052     destroy_counter_query(_machine_cpu_load);
1053     _machine_cpu_load = NULL;
1054   }
1055   pdh_release();
1056 }
1057 
1058 CPUPerformanceInterface::CPUPerformanceInterface() {
1059   _impl = NULL;
1060 }
1061 
1062 bool CPUPerformanceInterface::initialize() {
1063   _impl = new CPUPerformanceInterface::CPUPerformance();
1064   return _impl != NULL && _impl->initialize();
1065 }
1066 
1067 CPUPerformanceInterface::~CPUPerformanceInterface() {
1068   if (_impl != NULL) {
1069     delete _impl;
1070   }
1071 }
1072 
1073 int CPUPerformanceInterface::cpu_load(int which_logical_cpu, double* cpu_load) const {
1074   return _impl->cpu_load(which_logical_cpu, cpu_load);
1075 }
1076 
1077 int CPUPerformanceInterface::context_switch_rate(double* rate) const {
1078   return _impl->context_switch_rate(rate);
1079 }
1080 
1081 int CPUPerformanceInterface::cpu_load_total_process(double* cpu_load) const {
1082   return _impl->cpu_load_total_process(cpu_load);
1083 }
1084 
1085 int CPUPerformanceInterface::cpu_loads_process(double* pjvmUserLoad,
1086                                                double* pjvmKernelLoad,
1087                                                double* psystemTotalLoad) const {
1088   return _impl->cpu_loads_process(pjvmUserLoad, pjvmKernelLoad, psystemTotalLoad);
1089 }
1090 
1091 int CPUPerformanceInterface::CPUPerformance::cpu_load(int which_logical_cpu, double* cpu_load) {
1092   *cpu_load = .0;
1093   if (_machine_cpu_load == NULL || !_machine_cpu_load->initialized) {
1094     return OS_ERR;
1095   }
1096   assert(_machine_cpu_load != NULL, "invariant");
1097   assert(which_logical_cpu < _machine_cpu_load->noOfCounters, "invariant");
1098 
1099   if (collect_query_data(_machine_cpu_load)) {
1100     return OS_ERR;
1101   }
1102   // -1 is total (all cpus)
1103   const int counter_idx = -1 == which_logical_cpu ? _machine_cpu_load->noOfCounters - 1 : which_logical_cpu;
1104   PDH_FMT_COUNTERVALUE counter_value;
1105   formatted_counter_value(_machine_cpu_load->counters[counter_idx], PDH_FMT_DOUBLE, &counter_value);
1106   *cpu_load = counter_value.doubleValue / 100;
1107   return OS_OK;
1108 }
1109 
1110 int CPUPerformanceInterface::CPUPerformance::cpu_load_total_process(double* cpu_load) {
1111   *cpu_load = .0;
1112   if (_process_cpu_load == NULL || !_process_cpu_load->set.initialized) {
1113     return OS_ERR;
1114   }
1115   assert(_process_cpu_load != NULL, "invariant");
1116   if (collect_process_query_data(_process_cpu_load)) {
1117     return OS_ERR;
1118   }
1119   PDH_FMT_COUNTERVALUE counter_value;
1120   if (query_process_counter(_process_cpu_load, 0, PDH_FMT_DOUBLE | PDH_FMT_NOCAP100, &counter_value) != OS_OK) {
1121     return OS_ERR;
1122   }
1123   double process_load = counter_value.doubleValue / cpu_factor();
1124   process_load = MIN2<double>(1, process_load);
1125   process_load = MAX2<double>(0, process_load);
1126   *cpu_load = process_load;
1127   return OS_OK;
1128 }
1129 
1130 int CPUPerformanceInterface::CPUPerformance::cpu_loads_process(double* pjvmUserLoad,
1131                                                                double* pjvmKernelLoad,
1132                                                                double* psystemTotalLoad) {
1133   assert(pjvmUserLoad != NULL, "pjvmUserLoad is NULL!");
1134   assert(pjvmKernelLoad != NULL, "pjvmKernelLoad is NULL!");
1135   assert(psystemTotalLoad != NULL, "psystemTotalLoad is NULL!");
1136   *pjvmUserLoad = .0;
1137   *pjvmKernelLoad = .0;
1138   *psystemTotalLoad = .0;
1139 
1140   if (_process_cpu_load == NULL || !_process_cpu_load->set.initialized) {
1141     return OS_ERR;
1142   }
1143   assert(_process_cpu_load != NULL, "invariant");
1144   if (collect_process_query_data(_process_cpu_load)) {
1145     return OS_ERR;
1146   }
1147   double process_load = .0;
1148   PDH_FMT_COUNTERVALUE counter_value;
1149   // Read  PDH_PROCESSOR_TIME_IDX
1150   if (query_process_counter(_process_cpu_load, 0, PDH_FMT_DOUBLE | PDH_FMT_NOCAP100, &counter_value) != OS_OK) {
1151     return OS_ERR;
1152   }
1153   process_load = counter_value.doubleValue / cpu_factor();
1154   process_load = MIN2<double>(1, process_load);
1155   process_load = MAX2<double>(0, process_load);
1156   // Read PDH_PRIV_PROCESSOR_TIME_IDX
1157   if (query_process_counter(_process_cpu_load, 1, PDH_FMT_DOUBLE | PDH_FMT_NOCAP100, &counter_value) != OS_OK) {
1158     return OS_ERR;
1159   }
1160   double kernel_load = counter_value.doubleValue / cpu_factor();
1161   kernel_load = MIN2<double>(1, kernel_load);
1162   kernel_load = MAX2<double>(0, kernel_load);
1163   *pjvmKernelLoad = kernel_load;
1164 
1165   double user_load = process_load - kernel_load;
1166   user_load = MIN2<double>(1, user_load);
1167   user_load = MAX2<double>(0, user_load);
1168   *pjvmUserLoad = user_load;
1169 
1170   if (collect_query_data(_machine_cpu_load)) {
1171     return OS_ERR;
1172   }
1173   if (formatted_counter_value(_machine_cpu_load->counters[_machine_cpu_load->noOfCounters - 1], PDH_FMT_DOUBLE, &counter_value) != OS_OK) {
1174     return OS_ERR;
1175   }
1176   double machine_load = counter_value.doubleValue / 100;
1177   assert(machine_load >= 0, "machine_load is negative!");
1178   // clamp at user+system and 1.0
1179   if (*pjvmKernelLoad + *pjvmUserLoad > machine_load) {
1180     machine_load = MIN2(*pjvmKernelLoad + *pjvmUserLoad, 1.0);
1181   }
1182   *psystemTotalLoad = machine_load;
1183   return OS_OK;
1184 }
1185 
1186 int CPUPerformanceInterface::CPUPerformance::context_switch_rate(double* rate) {
1187   assert(rate != NULL, "invariant");
1188   *rate = .0;
1189   if (_context_switches == NULL || !_context_switches->initialized) {
1190     return OS_ERR;
1191   }
1192   assert(_context_switches != NULL, "invariant");
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, mtInternal);
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, mtInternal);
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 }
1382 
1383 class NetworkPerformanceInterface::NetworkPerformance : public CHeapObj<mtInternal> {
1384   friend class NetworkPerformanceInterface;
1385  private:
1386   bool _iphlp_attached;
1387 
1388   NetworkPerformance();
1389   NetworkPerformance(const NetworkPerformance& rhs); // no impl
1390   NetworkPerformance& operator=(const NetworkPerformance& rhs); // no impl
1391   bool initialize();
1392   ~NetworkPerformance();
1393   int network_utilization(NetworkInterface** network_interfaces) const;
1394 };
1395 
1396 NetworkPerformanceInterface::NetworkPerformance::NetworkPerformance()
1397 : _iphlp_attached(false) {
1398 }
1399 
1400 bool NetworkPerformanceInterface::NetworkPerformance::initialize() {
1401   _iphlp_attached = IphlpDll::IphlpAttach();
1402   return _iphlp_attached;
1403 }
1404 
1405 NetworkPerformanceInterface::NetworkPerformance::~NetworkPerformance() {
1406   if (_iphlp_attached) {
1407     IphlpDll::IphlpDetach();
1408   }
1409 }
1410 
1411 int NetworkPerformanceInterface::NetworkPerformance::network_utilization(NetworkInterface** network_interfaces) const {
1412   MIB_IF_TABLE2* table;
1413 
1414   if (IphlpDll::GetIfTable2(&table) != NO_ERROR) {
1415     return OS_ERR;
1416   }
1417 
1418   NetworkInterface* ret = NULL;
1419   for (ULONG i = 0; i < table->NumEntries; ++i) {
1420     if (table->Table[i].InterfaceAndOperStatusFlags.FilterInterface) {
1421       continue;
1422     }
1423 
1424     char buf[256];
1425     if (WideCharToMultiByte(CP_UTF8, 0, table->Table[i].Description, -1, buf, sizeof(buf), NULL, NULL) == 0) {
1426       continue;
1427     }
1428 
1429     NetworkInterface* cur = new NetworkInterface(buf, table->Table[i].InOctets, table->Table[i].OutOctets, ret);
1430     ret = cur;
1431   }
1432 
1433   IphlpDll::FreeMibTable(table);
1434   *network_interfaces = ret;
1435 
1436   return OS_OK;
1437 }
1438 
1439 NetworkPerformanceInterface::NetworkPerformanceInterface() {
1440   _impl = NULL;
1441 }
1442 
1443 NetworkPerformanceInterface::~NetworkPerformanceInterface() {
1444   if (_impl != NULL) {
1445     delete _impl;
1446   }
1447 }
1448 
1449 bool NetworkPerformanceInterface::initialize() {
1450   _impl = new NetworkPerformanceInterface::NetworkPerformance();
1451   return _impl != NULL && _impl->initialize();
1452 }
1453 
1454 int NetworkPerformanceInterface::network_utilization(NetworkInterface** network_interfaces) const {
1455   return _impl->network_utilization(network_interfaces);
1456 }