8080999: MemoryPoolMXBean.getUsageThresholdCount() returns incorrect value

Fixed race condition in the JMX code for the LowMemoryDetector.

Reviewed-by: kvn
This commit is contained in:
Tobias Hartmann 2015-09-14 07:02:50 +02:00
parent 9dcbe322e0
commit 3780022a87
2 changed files with 22 additions and 16 deletions

View File

@ -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 @@ SensorInfo::SensorInfo() {
// 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 @@ void SensorInfo::set_gauge_sensor_level(MemoryUsage usage, ThresholdSupport* hig
// 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::oops_do(OopClosure* f) {
}
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::process_pending_requests(TRAPS) {
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 @@ void SensorInfo::trigger(int count, TRAPS) {
{
// 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::trigger(int count, TRAPS) {
}
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 @@ void SensorInfo::clear(int count, TRAPS) {
&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;
}
}
//--------------------------------------------------------------

View File

@ -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 @@ public:
// 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);