Mercurial > hg > truffle
annotate src/share/vm/services/lowMemoryDetector.cpp @ 1721:413ad0331a0c
6977924: Changes for 6975078 produce build error with certain gcc versions
Summary: The changes introduced for 6975078 assign badHeapOopVal to the _allocation field in the ResourceObj class. In 32 bit linux builds with certain versions of gcc this assignment will be flagged as an error while compiling allocation.cpp. In 32 bit builds the constant value badHeapOopVal (which is cast to an intptr_t) is negative. The _allocation field is typed as an unsigned intptr_t and gcc catches this as an error.
Reviewed-by: jcoomes, ysr, phh
author | johnc |
---|---|
date | Wed, 18 Aug 2010 10:59:06 -0700 |
parents | c18cbe5936b8 |
children | f95d63e2154a |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1142
diff
changeset
|
2 * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1142
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1142
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1142
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 # include "incls/_precompiled.incl" | |
26 # include "incls/_lowMemoryDetector.cpp.incl" | |
27 | |
28 LowMemoryDetectorThread* LowMemoryDetector::_detector_thread = NULL; | |
29 volatile bool LowMemoryDetector::_enabled_for_collected_pools = false; | |
30 volatile jint LowMemoryDetector::_disabled_count = 0; | |
31 | |
32 void LowMemoryDetector::initialize() { | |
33 EXCEPTION_MARK; | |
34 | |
1142 | 35 instanceKlassHandle klass (THREAD, SystemDictionary::Thread_klass()); |
0 | 36 instanceHandle thread_oop = klass->allocate_instance_handle(CHECK); |
37 | |
38 const char thread_name[] = "Low Memory Detector"; | |
39 Handle string = java_lang_String::create_from_str(thread_name, CHECK); | |
40 | |
41 // Initialize thread_oop to put it into the system threadGroup | |
42 Handle thread_group (THREAD, Universe::system_thread_group()); | |
43 JavaValue result(T_VOID); | |
44 JavaCalls::call_special(&result, thread_oop, | |
45 klass, | |
46 vmSymbolHandles::object_initializer_name(), | |
47 vmSymbolHandles::threadgroup_string_void_signature(), | |
48 thread_group, | |
49 string, | |
50 CHECK); | |
51 | |
52 { | |
53 MutexLocker mu(Threads_lock); | |
54 _detector_thread = new LowMemoryDetectorThread(&low_memory_detector_thread_entry); | |
55 | |
56 // At this point it may be possible that no osthread was created for the | |
57 // JavaThread due to lack of memory. We would have to throw an exception | |
58 // in that case. However, since this must work and we do not allow | |
59 // exceptions anyway, check and abort if this fails. | |
60 if (_detector_thread == NULL || _detector_thread->osthread() == NULL) { | |
61 vm_exit_during_initialization("java.lang.OutOfMemoryError", | |
62 "unable to create new native thread"); | |
63 } | |
64 | |
65 java_lang_Thread::set_thread(thread_oop(), _detector_thread); | |
66 java_lang_Thread::set_priority(thread_oop(), NearMaxPriority); | |
67 java_lang_Thread::set_daemon(thread_oop()); | |
68 _detector_thread->set_threadObj(thread_oop()); | |
69 | |
70 Threads::add(_detector_thread); | |
71 Thread::start(_detector_thread); | |
72 } | |
73 } | |
74 | |
75 bool LowMemoryDetector::has_pending_requests() { | |
76 assert(LowMemory_lock->owned_by_self(), "Must own LowMemory_lock"); | |
77 bool has_requests = false; | |
78 int num_memory_pools = MemoryService::num_memory_pools(); | |
79 for (int i = 0; i < num_memory_pools; i++) { | |
80 MemoryPool* pool = MemoryService::get_memory_pool(i); | |
81 SensorInfo* sensor = pool->usage_sensor(); | |
82 if (sensor != NULL) { | |
83 has_requests = has_requests || sensor->has_pending_requests(); | |
84 } | |
85 | |
86 SensorInfo* gc_sensor = pool->gc_usage_sensor(); | |
87 if (gc_sensor != NULL) { | |
88 has_requests = has_requests || gc_sensor->has_pending_requests(); | |
89 } | |
90 } | |
91 return has_requests; | |
92 } | |
93 | |
94 void LowMemoryDetector::low_memory_detector_thread_entry(JavaThread* jt, TRAPS) { | |
95 while (true) { | |
96 bool sensors_changed = false; | |
97 | |
98 { | |
99 // _no_safepoint_check_flag is used here as LowMemory_lock is a | |
100 // special lock and the VMThread may acquire this lock at safepoint. | |
101 // Need state transition ThreadBlockInVM so that this thread | |
102 // will be handled by safepoint correctly when this thread is | |
103 // notified at a safepoint. | |
104 | |
105 // This ThreadBlockInVM object is not also considered to be | |
106 // suspend-equivalent because LowMemoryDetector threads are | |
107 // not visible to external suspension. | |
108 | |
109 ThreadBlockInVM tbivm(jt); | |
110 | |
111 MutexLockerEx ml(LowMemory_lock, Mutex::_no_safepoint_check_flag); | |
112 while (!(sensors_changed = has_pending_requests())) { | |
113 // wait until one of the sensors has pending requests | |
114 LowMemory_lock->wait(Mutex::_no_safepoint_check_flag); | |
115 } | |
116 } | |
117 | |
118 { | |
119 ResourceMark rm(THREAD); | |
120 HandleMark hm(THREAD); | |
121 | |
122 // No need to hold LowMemory_lock to call out to Java | |
123 int num_memory_pools = MemoryService::num_memory_pools(); | |
124 for (int i = 0; i < num_memory_pools; i++) { | |
125 MemoryPool* pool = MemoryService::get_memory_pool(i); | |
126 SensorInfo* sensor = pool->usage_sensor(); | |
127 SensorInfo* gc_sensor = pool->gc_usage_sensor(); | |
128 if (sensor != NULL && sensor->has_pending_requests()) { | |
129 sensor->process_pending_requests(CHECK); | |
130 } | |
131 if (gc_sensor != NULL && gc_sensor->has_pending_requests()) { | |
132 gc_sensor->process_pending_requests(CHECK); | |
133 } | |
134 } | |
135 } | |
136 } | |
137 } | |
138 | |
139 // This method could be called from any Java threads | |
140 // and also VMThread. | |
141 void LowMemoryDetector::detect_low_memory() { | |
142 MutexLockerEx ml(LowMemory_lock, Mutex::_no_safepoint_check_flag); | |
143 | |
144 bool has_pending_requests = false; | |
145 int num_memory_pools = MemoryService::num_memory_pools(); | |
146 for (int i = 0; i < num_memory_pools; i++) { | |
147 MemoryPool* pool = MemoryService::get_memory_pool(i); | |
148 SensorInfo* sensor = pool->usage_sensor(); | |
149 if (sensor != NULL && | |
150 pool->usage_threshold()->is_high_threshold_supported() && | |
151 pool->usage_threshold()->high_threshold() != 0) { | |
152 MemoryUsage usage = pool->get_memory_usage(); | |
153 sensor->set_gauge_sensor_level(usage, | |
154 pool->usage_threshold()); | |
155 has_pending_requests = has_pending_requests || sensor->has_pending_requests(); | |
156 } | |
157 } | |
158 | |
159 if (has_pending_requests) { | |
160 LowMemory_lock->notify_all(); | |
161 } | |
162 } | |
163 | |
164 // This method could be called from any Java threads | |
165 // and also VMThread. | |
166 void LowMemoryDetector::detect_low_memory(MemoryPool* pool) { | |
167 SensorInfo* sensor = pool->usage_sensor(); | |
168 if (sensor == NULL || | |
169 !pool->usage_threshold()->is_high_threshold_supported() || | |
170 pool->usage_threshold()->high_threshold() == 0) { | |
171 return; | |
172 } | |
173 | |
174 { | |
175 MutexLockerEx ml(LowMemory_lock, Mutex::_no_safepoint_check_flag); | |
176 | |
177 MemoryUsage usage = pool->get_memory_usage(); | |
178 sensor->set_gauge_sensor_level(usage, | |
179 pool->usage_threshold()); | |
180 if (sensor->has_pending_requests()) { | |
181 // notify sensor state update | |
182 LowMemory_lock->notify_all(); | |
183 } | |
184 } | |
185 } | |
186 | |
187 // Only called by VMThread at GC time | |
188 void LowMemoryDetector::detect_after_gc_memory(MemoryPool* pool) { | |
189 SensorInfo* sensor = pool->gc_usage_sensor(); | |
190 if (sensor == NULL || | |
191 !pool->gc_usage_threshold()->is_high_threshold_supported() || | |
192 pool->gc_usage_threshold()->high_threshold() == 0) { | |
193 return; | |
194 } | |
195 | |
196 { | |
197 MutexLockerEx ml(LowMemory_lock, Mutex::_no_safepoint_check_flag); | |
198 | |
199 MemoryUsage usage = pool->get_last_collection_usage(); | |
200 sensor->set_counter_sensor_level(usage, pool->gc_usage_threshold()); | |
201 | |
202 if (sensor->has_pending_requests()) { | |
203 // notify sensor state update | |
204 LowMemory_lock->notify_all(); | |
205 } | |
206 } | |
207 } | |
208 | |
209 // recompute enabled flag | |
210 void LowMemoryDetector::recompute_enabled_for_collected_pools() { | |
211 bool enabled = false; | |
212 int num_memory_pools = MemoryService::num_memory_pools(); | |
213 for (int i=0; i<num_memory_pools; i++) { | |
214 MemoryPool* pool = MemoryService::get_memory_pool(i); | |
215 if (pool->is_collected_pool() && is_enabled(pool)) { | |
216 enabled = true; | |
217 break; | |
218 } | |
219 } | |
220 _enabled_for_collected_pools = enabled; | |
221 } | |
222 | |
223 SensorInfo::SensorInfo() { | |
224 _sensor_obj = NULL; | |
225 _sensor_on = false; | |
226 _sensor_count = 0; | |
227 _pending_trigger_count = 0; | |
228 _pending_clear_count = 0; | |
229 } | |
230 | |
231 // When this method is used, the memory usage is monitored | |
232 // as a gauge attribute. Sensor notifications (trigger or | |
233 // clear) is only emitted at the first time it crosses | |
234 // a threshold. | |
235 // | |
236 // High and low thresholds are designed to provide a | |
237 // hysteresis mechanism to avoid repeated triggering | |
238 // of notifications when the attribute value makes small oscillations | |
239 // around the high or low threshold value. | |
240 // | |
241 // The sensor will be triggered if: | |
242 // (1) the usage is crossing above the high threshold and | |
243 // the sensor is currently off and no pending | |
244 // trigger requests; or | |
245 // (2) the usage is crossing above the high threshold and | |
246 // the sensor will be off (i.e. sensor is currently on | |
247 // and has pending clear requests). | |
248 // | |
249 // Subsequent crossings of the high threshold value do not cause | |
250 // any triggers unless the usage becomes less than the low threshold. | |
251 // | |
252 // The sensor will be cleared if: | |
253 // (1) the usage is crossing below the low threshold and | |
254 // the sensor is currently on and no pending | |
255 // clear requests; 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). | |
259 // | |
260 // Subsequent crossings of the low threshold value do not cause | |
261 // any clears unless the usage becomes greater than or equal | |
262 // to the high threshold. | |
263 // | |
264 // If the current level is between high and low threhsold, no change. | |
265 // | |
266 void SensorInfo::set_gauge_sensor_level(MemoryUsage usage, ThresholdSupport* high_low_threshold) { | |
267 assert(high_low_threshold->is_high_threshold_supported(), "just checking"); | |
268 | |
269 bool is_over_high = high_low_threshold->is_high_threshold_crossed(usage); | |
270 bool is_below_low = high_low_threshold->is_low_threshold_crossed(usage); | |
271 | |
272 assert(!(is_over_high && is_below_low), "Can't be both true"); | |
273 | |
274 if (is_over_high && | |
275 ((!_sensor_on && _pending_trigger_count == 0) || | |
276 _pending_clear_count > 0)) { | |
277 // low memory detected and need to increment the trigger pending count | |
278 // if the sensor is off or will be off due to _pending_clear_ > 0 | |
279 // Request to trigger the sensor | |
280 _pending_trigger_count++; | |
281 _usage = usage; | |
282 | |
283 if (_pending_clear_count > 0) { | |
284 // non-zero pending clear requests indicates that there are | |
285 // pending requests to clear this sensor. | |
286 // This trigger request needs to clear this clear count | |
287 // since the resulting sensor flag should be on. | |
288 _pending_clear_count = 0; | |
289 } | |
290 } else if (is_below_low && | |
291 ((_sensor_on && _pending_clear_count == 0) || | |
292 (_pending_trigger_count > 0 && _pending_clear_count == 0))) { | |
293 // memory usage returns below the threshold | |
294 // Request to clear the sensor if the sensor is on or will be on due to | |
295 // _pending_trigger_count > 0 and also no clear request | |
296 _pending_clear_count++; | |
297 } | |
298 } | |
299 | |
300 // When this method is used, the memory usage is monitored as a | |
301 // simple counter attribute. The sensor will be triggered | |
302 // whenever the usage is crossing the threshold to keep track | |
303 // of the number of times the VM detects such a condition occurs. | |
304 // | |
305 // High and low thresholds are designed to provide a | |
306 // hysteresis mechanism to avoid repeated triggering | |
307 // of notifications when the attribute value makes small oscillations | |
308 // around the high or low threshold value. | |
309 // | |
310 // The sensor will be triggered if: | |
311 // - the usage is crossing above the high threshold regardless | |
312 // of the current sensor state. | |
313 // | |
314 // The sensor will be cleared if: | |
315 // (1) the usage is crossing below the low threshold and | |
316 // the sensor is currently on; or | |
317 // (2) the usage is crossing below the low threshold and | |
318 // the sensor will be on (i.e. sensor is currently off | |
319 // and has pending trigger requests). | |
320 void SensorInfo::set_counter_sensor_level(MemoryUsage usage, ThresholdSupport* counter_threshold) { | |
321 assert(counter_threshold->is_high_threshold_supported(), "just checking"); | |
322 | |
323 bool is_over_high = counter_threshold->is_high_threshold_crossed(usage); | |
324 bool is_below_low = counter_threshold->is_low_threshold_crossed(usage); | |
325 | |
326 assert(!(is_over_high && is_below_low), "Can't be both true"); | |
327 | |
328 if (is_over_high) { | |
329 _pending_trigger_count++; | |
330 _usage = usage; | |
331 _pending_clear_count = 0; | |
332 } else if (is_below_low && (_sensor_on || _pending_trigger_count > 0)) { | |
333 _pending_clear_count++; | |
334 } | |
335 } | |
336 | |
337 void SensorInfo::oops_do(OopClosure* f) { | |
338 f->do_oop((oop*) &_sensor_obj); | |
339 } | |
340 | |
341 void SensorInfo::process_pending_requests(TRAPS) { | |
342 if (!has_pending_requests()) { | |
343 return; | |
344 } | |
345 | |
346 int pending_count = pending_trigger_count(); | |
347 if (pending_clear_count() > 0) { | |
348 clear(pending_count, CHECK); | |
349 } else { | |
350 trigger(pending_count, CHECK); | |
351 } | |
352 | |
353 } | |
354 | |
355 void SensorInfo::trigger(int count, TRAPS) { | |
356 assert(count <= _pending_trigger_count, "just checking"); | |
357 | |
358 if (_sensor_obj != NULL) { | |
359 klassOop k = Management::sun_management_Sensor_klass(CHECK); | |
360 instanceKlassHandle sensorKlass (THREAD, k); | |
361 Handle sensor_h(THREAD, _sensor_obj); | |
362 Handle usage_h = MemoryService::create_MemoryUsage_obj(_usage, CHECK); | |
363 | |
364 JavaValue result(T_VOID); | |
365 JavaCallArguments args(sensor_h); | |
366 args.push_int((int) count); | |
367 args.push_oop(usage_h); | |
368 | |
369 JavaCalls::call_virtual(&result, | |
370 sensorKlass, | |
371 vmSymbolHandles::trigger_name(), | |
372 vmSymbolHandles::trigger_method_signature(), | |
373 &args, | |
374 CHECK); | |
375 } | |
376 | |
377 { | |
378 // Holds LowMemory_lock and update the sensor state | |
379 MutexLockerEx ml(LowMemory_lock, Mutex::_no_safepoint_check_flag); | |
380 _sensor_on = true; | |
381 _sensor_count += count; | |
382 _pending_trigger_count = _pending_trigger_count - count; | |
383 } | |
384 } | |
385 | |
386 void SensorInfo::clear(int count, TRAPS) { | |
387 if (_sensor_obj != NULL) { | |
388 klassOop k = Management::sun_management_Sensor_klass(CHECK); | |
389 instanceKlassHandle sensorKlass (THREAD, k); | |
390 Handle sensor(THREAD, _sensor_obj); | |
391 | |
392 JavaValue result(T_VOID); | |
393 JavaCallArguments args(sensor); | |
394 args.push_int((int) count); | |
395 JavaCalls::call_virtual(&result, | |
396 sensorKlass, | |
397 vmSymbolHandles::clear_name(), | |
398 vmSymbolHandles::int_void_signature(), | |
399 &args, | |
400 CHECK); | |
401 } | |
402 | |
403 { | |
404 // Holds LowMemory_lock and update the sensor state | |
405 MutexLockerEx ml(LowMemory_lock, Mutex::_no_safepoint_check_flag); | |
406 _sensor_on = false; | |
407 _pending_clear_count = 0; | |
408 _pending_trigger_count = _pending_trigger_count - count; | |
409 } | |
410 } | |
411 | |
412 //-------------------------------------------------------------- | |
413 // Non-product code | |
414 | |
415 #ifndef PRODUCT | |
416 void SensorInfo::print() { | |
417 tty->print_cr("%s count = %ld pending_triggers = %ld pending_clears = %ld", | |
418 (_sensor_on ? "on" : "off"), | |
419 _sensor_count, _pending_trigger_count, _pending_clear_count); | |
420 } | |
421 | |
422 #endif // PRODUCT |