lowMemoryDetector.cpp revision 3602:da91efe96a93
1/*
2 * Copyright (c) 2003, 2012, 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 "classfile/systemDictionary.hpp"
27#include "classfile/vmSymbols.hpp"
28#include "oops/oop.inline.hpp"
29#include "runtime/interfaceSupport.hpp"
30#include "runtime/java.hpp"
31#include "runtime/javaCalls.hpp"
32#include "runtime/mutex.hpp"
33#include "runtime/mutexLocker.hpp"
34#include "services/lowMemoryDetector.hpp"
35#include "services/management.hpp"
36
37volatile bool LowMemoryDetector::_enabled_for_collected_pools = false;
38volatile jint LowMemoryDetector::_disabled_count = 0;
39
40bool LowMemoryDetector::has_pending_requests() {
41  assert(Service_lock->owned_by_self(), "Must own Service_lock");
42  bool has_requests = false;
43  int num_memory_pools = MemoryService::num_memory_pools();
44  for (int i = 0; i < num_memory_pools; i++) {
45    MemoryPool* pool = MemoryService::get_memory_pool(i);
46    SensorInfo* sensor = pool->usage_sensor();
47    if (sensor != NULL) {
48      has_requests = has_requests || sensor->has_pending_requests();
49    }
50
51    SensorInfo* gc_sensor = pool->gc_usage_sensor();
52    if (gc_sensor != NULL) {
53      has_requests = has_requests || gc_sensor->has_pending_requests();
54    }
55  }
56  return has_requests;
57}
58
59void LowMemoryDetector::process_sensor_changes(TRAPS) {
60  ResourceMark rm(THREAD);
61  HandleMark hm(THREAD);
62
63  // No need to hold Service_lock to call out to Java
64  int num_memory_pools = MemoryService::num_memory_pools();
65  for (int i = 0; i < num_memory_pools; i++) {
66    MemoryPool* pool = MemoryService::get_memory_pool(i);
67    SensorInfo* sensor = pool->usage_sensor();
68    SensorInfo* gc_sensor = pool->gc_usage_sensor();
69    if (sensor != NULL && sensor->has_pending_requests()) {
70      sensor->process_pending_requests(CHECK);
71    }
72    if (gc_sensor != NULL && gc_sensor->has_pending_requests()) {
73      gc_sensor->process_pending_requests(CHECK);
74    }
75  }
76}
77
78// This method could be called from any Java threads
79// and also VMThread.
80void LowMemoryDetector::detect_low_memory() {
81  MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
82
83  bool has_pending_requests = false;
84  int num_memory_pools = MemoryService::num_memory_pools();
85  for (int i = 0; i < num_memory_pools; i++) {
86    MemoryPool* pool = MemoryService::get_memory_pool(i);
87    SensorInfo* sensor = pool->usage_sensor();
88    if (sensor != NULL &&
89        pool->usage_threshold()->is_high_threshold_supported() &&
90        pool->usage_threshold()->high_threshold() != 0) {
91      MemoryUsage usage = pool->get_memory_usage();
92      sensor->set_gauge_sensor_level(usage,
93                                     pool->usage_threshold());
94      has_pending_requests = has_pending_requests || sensor->has_pending_requests();
95    }
96  }
97
98  if (has_pending_requests) {
99    Service_lock->notify_all();
100  }
101}
102
103// This method could be called from any Java threads
104// and also VMThread.
105void LowMemoryDetector::detect_low_memory(MemoryPool* pool) {
106  SensorInfo* sensor = pool->usage_sensor();
107  if (sensor == NULL ||
108      !pool->usage_threshold()->is_high_threshold_supported() ||
109      pool->usage_threshold()->high_threshold() == 0) {
110    return;
111  }
112
113  {
114    MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
115
116    MemoryUsage usage = pool->get_memory_usage();
117    sensor->set_gauge_sensor_level(usage,
118                                   pool->usage_threshold());
119    if (sensor->has_pending_requests()) {
120      // notify sensor state update
121      Service_lock->notify_all();
122    }
123  }
124}
125
126// Only called by VMThread at GC time
127void LowMemoryDetector::detect_after_gc_memory(MemoryPool* pool) {
128  SensorInfo* sensor = pool->gc_usage_sensor();
129  if (sensor == NULL ||
130      !pool->gc_usage_threshold()->is_high_threshold_supported() ||
131      pool->gc_usage_threshold()->high_threshold() == 0) {
132    return;
133  }
134
135  {
136    MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
137
138    MemoryUsage usage = pool->get_last_collection_usage();
139    sensor->set_counter_sensor_level(usage, pool->gc_usage_threshold());
140
141    if (sensor->has_pending_requests()) {
142      // notify sensor state update
143      Service_lock->notify_all();
144    }
145  }
146}
147
148// recompute enabled flag
149void LowMemoryDetector::recompute_enabled_for_collected_pools() {
150  bool enabled = false;
151  int num_memory_pools = MemoryService::num_memory_pools();
152  for (int i=0; i<num_memory_pools; i++) {
153    MemoryPool* pool = MemoryService::get_memory_pool(i);
154    if (pool->is_collected_pool() && is_enabled(pool)) {
155      enabled = true;
156      break;
157    }
158  }
159  _enabled_for_collected_pools = enabled;
160}
161
162SensorInfo::SensorInfo() {
163  _sensor_obj = NULL;
164  _sensor_on = false;
165  _sensor_count = 0;
166  _pending_trigger_count = 0;
167  _pending_clear_count = 0;
168}
169
170// When this method is used, the memory usage is monitored
171// as a gauge attribute.  Sensor notifications (trigger or
172// clear) is only emitted at the first time it crosses
173// a threshold.
174//
175// High and low thresholds are designed to provide a
176// hysteresis mechanism to avoid repeated triggering
177// of notifications when the attribute value makes small oscillations
178// around the high or low threshold value.
179//
180// The sensor will be triggered if:
181//  (1) the usage is crossing above the high threshold and
182//      the sensor is currently off and no pending
183//      trigger requests; or
184//  (2) the usage is crossing above the high threshold and
185//      the sensor will be off (i.e. sensor is currently on
186//      and has pending clear requests).
187//
188// Subsequent crossings of the high threshold value do not cause
189// any triggers unless the usage becomes less than the low threshold.
190//
191// The sensor will be cleared if:
192//  (1) the usage is crossing below the low threshold and
193//      the sensor is currently on and no pending
194//      clear requests; or
195//  (2) the usage is crossing below the low threshold and
196//      the sensor will be on (i.e. sensor is currently off
197//      and has pending trigger requests).
198//
199// Subsequent crossings of the low threshold value do not cause
200// any clears unless the usage becomes greater than or equal
201// to the high threshold.
202//
203// If the current level is between high and low threhsold, no change.
204//
205void SensorInfo::set_gauge_sensor_level(MemoryUsage usage, ThresholdSupport* high_low_threshold) {
206  assert(high_low_threshold->is_high_threshold_supported(), "just checking");
207
208  bool is_over_high = high_low_threshold->is_high_threshold_crossed(usage);
209  bool is_below_low = high_low_threshold->is_low_threshold_crossed(usage);
210
211  assert(!(is_over_high && is_below_low), "Can't be both true");
212
213  if (is_over_high &&
214        ((!_sensor_on && _pending_trigger_count == 0) ||
215         _pending_clear_count > 0)) {
216    // low memory detected and need to increment the trigger pending count
217    // if the sensor is off or will be off due to _pending_clear_ > 0
218    // Request to trigger the sensor
219    _pending_trigger_count++;
220    _usage = usage;
221
222    if (_pending_clear_count > 0) {
223      // non-zero pending clear requests indicates that there are
224      // pending requests to clear this sensor.
225      // This trigger request needs to clear this clear count
226      // since the resulting sensor flag should be on.
227      _pending_clear_count = 0;
228    }
229  } else if (is_below_low &&
230               ((_sensor_on && _pending_clear_count == 0) ||
231                (_pending_trigger_count > 0 && _pending_clear_count == 0))) {
232    // memory usage returns below the threshold
233    // Request to clear the sensor if the sensor is on or will be on due to
234    // _pending_trigger_count > 0 and also no clear request
235    _pending_clear_count++;
236  }
237}
238
239// When this method is used, the memory usage is monitored as a
240// simple counter attribute.  The sensor will be triggered
241// whenever the usage is crossing the threshold to keep track
242// of the number of times the VM detects such a condition occurs.
243//
244// High and low thresholds are designed to provide a
245// hysteresis mechanism to avoid repeated triggering
246// of notifications when the attribute value makes small oscillations
247// around the high or low threshold value.
248//
249// The sensor will be triggered if:
250//   - the usage is crossing above the high threshold regardless
251//     of the current sensor state.
252//
253// The sensor will be cleared if:
254//  (1) the usage is crossing below the low threshold and
255//      the sensor is currently on; or
256//  (2) the usage is crossing below the low threshold and
257//      the sensor will be on (i.e. sensor is currently off
258//      and has pending trigger requests).
259void SensorInfo::set_counter_sensor_level(MemoryUsage usage, ThresholdSupport* counter_threshold) {
260  assert(counter_threshold->is_high_threshold_supported(), "just checking");
261
262  bool is_over_high = counter_threshold->is_high_threshold_crossed(usage);
263  bool is_below_low = counter_threshold->is_low_threshold_crossed(usage);
264
265  assert(!(is_over_high && is_below_low), "Can't be both true");
266
267  if (is_over_high) {
268    _pending_trigger_count++;
269    _usage = usage;
270    _pending_clear_count = 0;
271  } else if (is_below_low && (_sensor_on || _pending_trigger_count > 0)) {
272    _pending_clear_count++;
273  }
274}
275
276void SensorInfo::oops_do(OopClosure* f) {
277  f->do_oop((oop*) &_sensor_obj);
278}
279
280void SensorInfo::process_pending_requests(TRAPS) {
281  if (!has_pending_requests()) {
282    return;
283  }
284
285  int pending_count = pending_trigger_count();
286  if (pending_clear_count() > 0) {
287    clear(pending_count, CHECK);
288  } else {
289    trigger(pending_count, CHECK);
290  }
291
292}
293
294void SensorInfo::trigger(int count, TRAPS) {
295  assert(count <= _pending_trigger_count, "just checking");
296
297  if (_sensor_obj != NULL) {
298    Klass* k = Management::sun_management_Sensor_klass(CHECK);
299    instanceKlassHandle sensorKlass (THREAD, k);
300    Handle sensor_h(THREAD, _sensor_obj);
301    Handle usage_h = MemoryService::create_MemoryUsage_obj(_usage, CHECK);
302
303    JavaValue result(T_VOID);
304    JavaCallArguments args(sensor_h);
305    args.push_int((int) count);
306    args.push_oop(usage_h);
307
308    JavaCalls::call_virtual(&result,
309                            sensorKlass,
310                            vmSymbols::trigger_name(),
311                            vmSymbols::trigger_method_signature(),
312                            &args,
313                            CHECK);
314  }
315
316  {
317    // Holds Service_lock and update the sensor state
318    MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
319    _sensor_on = true;
320    _sensor_count += count;
321    _pending_trigger_count = _pending_trigger_count - count;
322  }
323}
324
325void SensorInfo::clear(int count, TRAPS) {
326  if (_sensor_obj != NULL) {
327    Klass* k = Management::sun_management_Sensor_klass(CHECK);
328    instanceKlassHandle sensorKlass (THREAD, k);
329    Handle sensor(THREAD, _sensor_obj);
330
331    JavaValue result(T_VOID);
332    JavaCallArguments args(sensor);
333    args.push_int((int) count);
334    JavaCalls::call_virtual(&result,
335                            sensorKlass,
336                            vmSymbols::clear_name(),
337                            vmSymbols::int_void_signature(),
338                            &args,
339                            CHECK);
340  }
341
342  {
343    // Holds Service_lock and update the sensor state
344    MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
345    _sensor_on = false;
346    _pending_clear_count = 0;
347    _pending_trigger_count = _pending_trigger_count - count;
348  }
349}
350
351//--------------------------------------------------------------
352// Non-product code
353
354#ifndef PRODUCT
355void SensorInfo::print() {
356  tty->print_cr("%s count = %ld pending_triggers = %ld pending_clears = %ld",
357                (_sensor_on ? "on" : "off"),
358                _sensor_count, _pending_trigger_count, _pending_clear_count);
359}
360
361#endif // PRODUCT
362