< prev index next >

src/hotspot/os/windows/os_perf_windows.cpp

Print this page
rev 50222 : 8203321: assert(current_query_index < process_query_set->size) failed: invariant
Reviewed-by:

@@ -116,10 +116,15 @@
   MultiCounterQueryP queries;
   int                size;
   bool               initialized;
 } MultiCounterQuerySetS, *MultiCounterQuerySetP;
 
+typedef struct {
+  MultiCounterQuerySetS set;
+  int                   process_index;
+} ProcessQueryS, *ProcessQueryP;
+
 static void pdh_cleanup(HQUERY* const query, HCOUNTER* const counter) {
   if (counter != NULL && *counter != NULL) {
     PdhDll::PdhRemoveCounter(*counter);
     *counter = NULL;
   }

@@ -156,22 +161,31 @@
     pdh_cleanup(&counter_query->query.query, NULL);
     FREE_C_HEAP_ARRAY(MultiCounterQueryS, counter_query);
   }
 }
 
-static void destroy_counter_query(MultiCounterQuerySetP counter_query_set) {
+static void destroy_multi_counter_query(MultiCounterQuerySetP counter_query_set) {
   for (int i = 0; i < counter_query_set->size; i++) {
     for (int j = 0; j < counter_query_set->queries[i].noOfCounters; ++j) {
       pdh_cleanup(NULL, &counter_query_set->queries[i].counters[j]);
     }
     FREE_C_HEAP_ARRAY(char, counter_query_set->queries[i].counters);
     pdh_cleanup(&counter_query_set->queries[i].query.query, NULL);
   }
   FREE_C_HEAP_ARRAY(MultiCounterQueryS, counter_query_set->queries);
+}
+
+static void destroy_counter_query(MultiCounterQuerySetP counter_query_set) {
+  destroy_multi_counter_query(counter_query_set);
   FREE_C_HEAP_ARRAY(MultiCounterQuerySetS, counter_query_set);
 }
 
+static void destroy_counter_query(ProcessQueryP process_query) {
+  destroy_multi_counter_query(&process_query->set);
+  FREE_C_HEAP_ARRAY(ProcessQueryS, process_query);
+}
+
 static int open_query(HQUERY* query) {
   return PdhDll::PdhOpenQuery(NULL, 0, query);
 }
 
 template <typename QueryP>

@@ -202,10 +216,15 @@
     }
   }
   return OS_OK;
 }
 
+static int allocate_counters(ProcessQueryP process_query, size_t nofCounters) {
+  assert(process_query != NULL, "invariant");
+  return allocate_counters(&process_query->set, nofCounters);
+}
+
 static void deallocate_counters(MultiCounterQueryP query) {
   if (query->counters != NULL) {
     FREE_C_HEAP_ARRAY(char, query->counters);
     query->counters = NULL;
     query->noOfCounters = 0;

@@ -260,11 +279,10 @@
   return OS_OK;
 }
 
 static OSReturn add_process_counter(MultiCounterQueryP query, int slot_index, const char* path, bool first_sample_on_init) {
   assert(query != NULL, "invariant");
-  assert(query != NULL, "invariant");
   assert(slot_index < query->noOfCounters, "invariant");
   assert(query->counters[slot_index] == NULL, "invariant");
   const OSReturn ret = add_counter(query, &query->counters[slot_index], path, first_sample_on_init);
   if (OS_OK == ret) {
     if (slot_index + 1 == query->noOfCounters) {

@@ -324,32 +342,34 @@
 *
 * current_query_index_for_process() keeps track of the current "correct" query
 * (in order to keep this index valid when the list resets from underneath,
 * ensure to call current_query_index_for_process() before every query involving
 * Process object instance data).
+*
+* if unable to query, returns OS_ERR(-1)
 */
 static int current_query_index_for_process() {
   assert(process_image_name != NULL, "invariant");
   assert(pdh_IDProcess_counter_fmt != NULL, "invariant");
   HQUERY tmpQuery = NULL;
   if (open_query(&tmpQuery) != ERROR_SUCCESS) {
-    return 0;
+    return OS_ERR;
   }
   char counter[512];
   HCOUNTER handle_counter = NULL;
   // iterate over all instance indexes and try to find our own pid
   for (int index = 0; index < max_intx; index++) {
     jio_snprintf(counter, sizeof(counter) - 1, pdh_IDProcess_counter_fmt, index);
     assert(strlen(counter) < sizeof(counter), "invariant");
     if (PdhDll::PdhAddCounter(tmpQuery, counter, 0, &handle_counter) != ERROR_SUCCESS) {
       pdh_cleanup(&tmpQuery, &handle_counter);
-      return 0;
+      return OS_ERR;
     }
     const PDH_STATUS res = PdhDll::PdhCollectQueryData(tmpQuery);
     if (res == PDH_INVALID_HANDLE || res == PDH_NO_DATA) {
       pdh_cleanup(&tmpQuery, &handle_counter);
-      return 0;
+      return OS_ERR;
     } else {
       PDH_FMT_COUNTERVALUE counter_value;
       formatted_counter_value(handle_counter, PDH_FMT_LONG, &counter_value);
       pdh_cleanup(NULL, &handle_counter);
       if ((LONG)os::current_process_id() == counter_value.longValue) {

@@ -357,48 +377,77 @@
         return index;
       }
     }
   }
   pdh_cleanup(&tmpQuery, NULL);
-  return 0;
-}
-
-static MultiCounterQuerySetP create_process_counter_query() {
-  MultiCounterQuerySetP const query = NEW_C_HEAP_ARRAY(MultiCounterQuerySetS, 1, mtInternal);
-  memset(query, 0, sizeof(MultiCounterQuerySetS));
-  const int current_process_idx = current_query_index_for_process();
-  query->queries = NEW_C_HEAP_ARRAY(MultiCounterQueryS, current_process_idx + 1, mtInternal);
-  memset(query->queries, 0, sizeof(MultiCounterQueryS) * (current_process_idx + 1));
-  query->size = current_process_idx + 1;
-  return query;
+  return OS_ERR;
 }
 
-static MultiCounterQueryP current_process_counter_query(MultiCounterQuerySetP process_query_set) {
-  assert(process_query_set != NULL, "invariant");
-  const int current_query_index = current_query_index_for_process();
-  assert(current_query_index < process_query_set->size, "invariant");
-  return &process_query_set->queries[current_query_index];
+static ProcessQueryP create_process_query() {
+  ProcessQueryP const process_query = NEW_C_HEAP_ARRAY(ProcessQueryS, 1, mtInternal);
+  memset(process_query, 0, sizeof(ProcessQueryS));
+  const int process_index = current_query_index_for_process();
+  const int current_process_idx = (OS_ERR == process_index) ? 0 : process_index;
+  process_query->set.queries = NEW_C_HEAP_ARRAY(MultiCounterQueryS, current_process_idx + 1, mtInternal);
+  memset(process_query->set.queries, 0, sizeof(MultiCounterQueryS) * (current_process_idx + 1));
+  process_query->process_index = current_process_idx;
+  process_query->set.size = current_process_idx + 1;
+  assert(process_query->set.size > process_query->process_index, "invariant");
+  return process_query;
+}
+
+static MultiCounterQueryP current_process_counter_query(ProcessQueryP process_query) {
+  assert(process_query != NULL, "invariant");
+  assert(process_query->process_index < process_query->set.size, "invariant");
+  return &process_query->set.queries[process_query->process_index];
 }
 
 static void clear_multi_counter(MultiCounterQueryP query) {
   for (int i = 0; i < query->noOfCounters; ++i) {
     pdh_cleanup(NULL, &query->counters[i]);
   }
   pdh_cleanup(&query->query.query, NULL);
+  query->initialized = false;
 }
 
-static int collect_process_query_data(MultiCounterQuerySetP counter_query_set) {
+static int ensure_valid_process_query_index(ProcessQueryP process_query) {
+  assert(process_query != NULL, "invariant");
+  const int previous_process_idx = process_query->process_index;
+  if (previous_process_idx == 0) {
+    return previous_process_idx;
+  }
   const int current_process_idx = current_query_index_for_process();
-  while (current_process_idx < counter_query_set->size - 1) {
-    const int new_size = --counter_query_set->size;
-    clear_multi_counter(&counter_query_set->queries[new_size]);
+  if (current_process_idx == previous_process_idx || OS_ERR == current_process_idx ||
+    current_process_idx >= process_query->set.size) {
+    return previous_process_idx;
   }
-  return collect_query_data(&counter_query_set->queries[current_process_idx]);
+
+  assert(current_process_idx >= 0 && current_process_idx < process_query->set.size, "out of bounds!");
+  while (current_process_idx < process_query->set.size - 1) {
+    const int new_size = --process_query->set.size;
+    clear_multi_counter(&process_query->set.queries[new_size]);
+  }
+  assert(current_process_idx < process_query->set.size, "invariant");
+  process_query->process_index = current_process_idx;
+  return current_process_idx;
+}
+
+static MultiCounterQueryP current_process_query(ProcessQueryP process_query) {
+  assert(process_query != NULL, "invariant");
+  const int current_process_idx = ensure_valid_process_query_index(process_query);
+  assert(current_process_idx == process_query->process_index, "invariant");
+  assert(current_process_idx < process_query->set.size, "invariant");
+  return &process_query->set.queries[current_process_idx];
 }
 
-static int query_process_counter(MultiCounterQuerySetP process_query_set, int slot_index, DWORD format, PDH_FMT_COUNTERVALUE* const value) {
-  MultiCounterQueryP const current_query = current_process_counter_query(process_query_set);
+static int collect_process_query_data(ProcessQueryP process_query) {
+  assert(process_query != NULL, "invariant");
+  return collect_query_data(current_process_query(process_query));
+}
+
+static int query_process_counter(ProcessQueryP process_query, int slot_index, DWORD format, PDH_FMT_COUNTERVALUE* const value) {
+  MultiCounterQueryP const current_query = current_process_counter_query(process_query);
   assert(current_query != NULL, "invariant");
   assert(slot_index < current_query->noOfCounters, "invariant");
   assert(current_query->counters[slot_index] != NULL, "invariant");
   return formatted_counter_value(current_query->counters[slot_index], format, value);
 }

@@ -808,31 +857,31 @@
   }
   assert(cpu_query->noOfCounters == logical_cpu_count + 1, "invariant");
   return initialize_cpu_query_counters(cpu_query, pdh_counter_idx);
 }
 
-static int initialize_process_counter(MultiCounterQuerySetP query_set, int slot_index, DWORD pdh_counter_index) {
+static int initialize_process_counter(ProcessQueryP process_query, int slot_index, DWORD pdh_counter_index) {
   char* localized_process_object;
   if (lookup_name_by_index(PDH_PROCESS_IDX, &localized_process_object) != OS_OK) {
     return OS_ERR;
   }
   assert(localized_process_object != NULL, "invariant");
   char* localized_counter_name;
   if (lookup_name_by_index(pdh_counter_index, &localized_counter_name) != OS_OK) {
     return OS_ERR;
   }
   assert(localized_counter_name != NULL, "invariant");
-  for (int i = 0; i < query_set->size; ++i) {
+  for (int i = 0; i < process_query->set.size; ++i) {
     char instanceIndexBuffer[32];
     const char* counter_path = make_fully_qualified_counter_path(localized_process_object,
                                                                  localized_counter_name,
                                                                  process_image_name,
                                                                  itoa(i, instanceIndexBuffer, 10));
     if (counter_path == NULL) {
       return OS_ERR;
     }
-    MultiCounterQueryP const query = &query_set->queries[i];
+    MultiCounterQueryP const query = &process_query->set.queries[i];
     if (add_process_counter(query, slot_index, counter_path, true)) {
       return OS_ERR;
     }
   }
   return OS_OK;

@@ -915,11 +964,11 @@
 
 class CPUPerformanceInterface::CPUPerformance : public CHeapObj<mtInternal> {
   friend class CPUPerformanceInterface;
  private:
   CounterQueryP _context_switches;
-  MultiCounterQuerySetP _process_cpu_load;
+  ProcessQueryP _process_cpu_load;
   MultiCounterQueryP _machine_cpu_load;
 
   int cpu_load(int which_logical_cpu, double* cpu_load);
   int context_switch_rate(double* rate);
   int cpu_load_total_process(double* cpu_load);

@@ -967,11 +1016,11 @@
   }
   _context_switches = create_counter_query(PDH_SYSTEM_IDX, PDH_CONTEXT_SWITCH_RATE_IDX);
   if (_context_switches == NULL) {
     return false;
   }
-  _process_cpu_load = create_process_counter_query();
+  _process_cpu_load = create_process_query();
   if (_process_cpu_load == NULL) {
     return false;
   }
   if (allocate_counters(_process_cpu_load, 2) != OS_OK) {
     return false;

@@ -980,11 +1029,11 @@
     return false;
   }
   if (initialize_process_counter(_process_cpu_load, 1, PDH_PRIV_PROCESSOR_TIME_IDX) != OS_OK) {
     return false;
   }
-  _process_cpu_load->initialized = true;
+  _process_cpu_load->set.initialized = true;
 
   _machine_cpu_load = create_multi_counter_query();
   if (_machine_cpu_load == NULL) {
     return false;
   }

@@ -1062,11 +1111,11 @@
 }
 
 int CPUPerformanceInterface::CPUPerformance::cpu_load_total_process(double* cpu_load) {
   assert(_process_cpu_load != NULL, "invariant");
   *cpu_load = .0;
-  if (!_process_cpu_load->initialized) {
+  if (!_process_cpu_load->set.initialized) {
     return OS_ERR;
   }
   if (collect_process_query_data(_process_cpu_load)) {
     return OS_ERR;
   }

@@ -1088,11 +1137,11 @@
   assert(pjvmKernelLoad != NULL, "pjvmKernelLoad is NULL!");
   assert(psystemTotalLoad != NULL, "psystemTotalLoad is NULL!");
   *pjvmUserLoad = .0;
   *pjvmKernelLoad = .0;
   *psystemTotalLoad = .0;
-  if (!_process_cpu_load->initialized) {
+  if (!_process_cpu_load->set.initialized) {
     return OS_ERR;
   }
   if (collect_process_query_data(_process_cpu_load)) {
     return OS_ERR;
   }
< prev index next >