8080999: MemoryPoolMXBean.getUsageThresholdCount() returns incorrect value
authorthartmann
Mon, 14 Sep 2015 07:02:50 +0200
changeset 32728 c94c99524ae9
parent 32465 d38126f16dbe
child 32729 31b285853bb7
8080999: MemoryPoolMXBean.getUsageThresholdCount() returns incorrect value Summary: Fixed race condition in the JMX code for the LowMemoryDetector. Reviewed-by: kvn
hotspot/src/share/vm/services/lowMemoryDetector.cpp
hotspot/src/share/vm/services/lowMemoryDetector.hpp
--- a/hotspot/src/share/vm/services/lowMemoryDetector.cpp	Wed Aug 26 12:43:15 2015 +0200
+++ b/hotspot/src/share/vm/services/lowMemoryDetector.cpp	Mon Sep 14 07:02:50 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -200,9 +200,10 @@
 // any clears unless the usage becomes greater than or equal
 // to the high threshold.
 //
-// If the current level is between high and low threhsold, no change.
+// If the current level is between high and low threshold, no change.
 //
 void SensorInfo::set_gauge_sensor_level(MemoryUsage usage, ThresholdSupport* high_low_threshold) {
+  assert(Service_lock->owned_by_self(), "Must own Service_lock");
   assert(high_low_threshold->is_high_threshold_supported(), "just checking");
 
   bool is_over_high = high_low_threshold->is_high_threshold_crossed(usage);
@@ -257,6 +258,7 @@
 //      the sensor will be on (i.e. sensor is currently off
 //      and has pending trigger requests).
 void SensorInfo::set_counter_sensor_level(MemoryUsage usage, ThresholdSupport* counter_threshold) {
+  assert(Service_lock->owned_by_self(), "Must own Service_lock");
   assert(counter_threshold->is_high_threshold_supported(), "just checking");
 
   bool is_over_high = counter_threshold->is_high_threshold_crossed(usage);
@@ -278,9 +280,7 @@
 }
 
 void SensorInfo::process_pending_requests(TRAPS) {
-  if (!has_pending_requests()) {
-    return;
-  }
+  assert(has_pending_requests(), "Must have pending request");
 
   int pending_count = pending_trigger_count();
   if (pending_clear_count() > 0) {
@@ -293,7 +293,6 @@
 
 void SensorInfo::trigger(int count, TRAPS) {
   assert(count <= _pending_trigger_count, "just checking");
-
   if (_sensor_obj != NULL) {
     Klass* k = Management::sun_management_Sensor_klass(CHECK);
     instanceKlassHandle sensorKlass (THREAD, k);
@@ -316,6 +315,7 @@
   {
     // Holds Service_lock and update the sensor state
     MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
+    assert(_pending_trigger_count > 0, "Must have pending trigger");
     _sensor_on = true;
     _sensor_count += count;
     _pending_trigger_count = _pending_trigger_count - count;
@@ -323,6 +323,20 @@
 }
 
 void SensorInfo::clear(int count, TRAPS) {
+  {
+    // Holds Service_lock and update the sensor state
+    MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
+    if (_pending_clear_count == 0) {
+      // Bail out if we lost a race to set_*_sensor_level() which may have
+      // reactivated the sensor in the meantime because it was triggered again.
+      return;
+    }
+    _sensor_on = false;
+    _sensor_count += count;
+    _pending_clear_count = 0;
+    _pending_trigger_count = _pending_trigger_count - count;
+  }
+
   if (_sensor_obj != NULL) {
     Klass* k = Management::sun_management_Sensor_klass(CHECK);
     instanceKlassHandle sensorKlass (THREAD, k);
@@ -338,14 +352,6 @@
                             &args,
                             CHECK);
   }
-
-  {
-    // Holds Service_lock and update the sensor state
-    MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
-    _sensor_on = false;
-    _pending_clear_count = 0;
-    _pending_trigger_count = _pending_trigger_count - count;
-  }
 }
 
 //--------------------------------------------------------------
--- a/hotspot/src/share/vm/services/lowMemoryDetector.hpp	Wed Aug 26 12:43:15 2015 +0200
+++ b/hotspot/src/share/vm/services/lowMemoryDetector.hpp	Mon Sep 14 07:02:50 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -180,7 +180,7 @@
   // any clears unless the usage becomes greater than or equal
   // to the high threshold.
   //
-  // If the current level is between high and low threhsold, no change.
+  // If the current level is between high and low threshold, no change.
   //
   void set_gauge_sensor_level(MemoryUsage usage, ThresholdSupport* high_low_threshold);