Mercurial > hg > graal-jvmci-8
annotate src/share/vm/prims/jvmtiRawMonitor.cpp @ 10241:d17700c82d7d
8006088: Incompatible heap size flags accepted by VM
Summary: Make processing of minimum, initial and maximum heap size more intiutive by removing previous limitations on allowed values, and make error reporting consistent. Further, fix errors in ergonomic heap sizing.
Reviewed-by: johnc, jwilhelm, tamao
author | tschatzl |
---|---|
date | Mon, 06 May 2013 17:19:42 +0200 |
parents | b9a9ed0f8eeb |
children | ce8f6bb717c9 |
rev | line source |
---|---|
1878 | 1 /* |
6842
b9a9ed0f8eeb
7197424: update copyright year to match last edit in jdk8 hotspot repository
mikael
parents:
6197
diff
changeset
|
2 * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. |
1878 | 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 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "prims/jvmtiRawMonitor.hpp" | |
27 #include "runtime/interfaceSupport.hpp" | |
28 #include "runtime/thread.hpp" | |
1878 | 29 |
6197 | 30 GrowableArray<JvmtiRawMonitor*> *JvmtiPendingMonitors::_monitors = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<JvmtiRawMonitor*>(1,true); |
1878 | 31 |
32 void JvmtiPendingMonitors::transition_raw_monitors() { | |
33 assert((Threads::number_of_threads()==1), | |
34 "Java thread has not created yet or more than one java thread \ | |
35 is running. Raw monitor transition will not work"); | |
36 JavaThread *current_java_thread = JavaThread::current(); | |
37 assert(current_java_thread->thread_state() == _thread_in_vm, "Must be in vm"); | |
38 { | |
39 ThreadBlockInVM __tbivm(current_java_thread); | |
40 for(int i=0; i< count(); i++) { | |
41 JvmtiRawMonitor *rmonitor = monitors()->at(i); | |
42 int r = rmonitor->raw_enter(current_java_thread); | |
43 assert(r == ObjectMonitor::OM_OK, "raw_enter should have worked"); | |
44 } | |
45 } | |
46 // pending monitors are converted to real monitor so delete them all. | |
47 dispose(); | |
48 } | |
49 | |
50 // | |
51 // class JvmtiRawMonitor | |
52 // | |
53 | |
54 JvmtiRawMonitor::JvmtiRawMonitor(const char *name) { | |
55 #ifdef ASSERT | |
6197 | 56 _name = strcpy(NEW_C_HEAP_ARRAY(char, strlen(name) + 1, mtInternal), name); |
1878 | 57 #else |
58 _name = NULL; | |
59 #endif | |
60 _magic = JVMTI_RM_MAGIC; | |
61 } | |
62 | |
63 JvmtiRawMonitor::~JvmtiRawMonitor() { | |
64 #ifdef ASSERT | |
65 FreeHeap(_name); | |
66 #endif | |
67 _magic = 0; | |
68 } | |
69 | |
70 | |
71 bool | |
72 JvmtiRawMonitor::is_valid() { | |
73 int value = 0; | |
74 | |
75 // This object might not be a JvmtiRawMonitor so we can't assume | |
76 // the _magic field is properly aligned. Get the value in a safe | |
77 // way and then check against JVMTI_RM_MAGIC. | |
78 | |
79 switch (sizeof(_magic)) { | |
80 case 2: | |
81 value = Bytes::get_native_u2((address)&_magic); | |
82 break; | |
83 | |
84 case 4: | |
85 value = Bytes::get_native_u4((address)&_magic); | |
86 break; | |
87 | |
88 case 8: | |
89 value = Bytes::get_native_u8((address)&_magic); | |
90 break; | |
91 | |
92 default: | |
93 guarantee(false, "_magic field is an unexpected size"); | |
94 } | |
95 | |
96 return value == JVMTI_RM_MAGIC; | |
97 } | |
98 | |
99 // ------------------------------------------------------------------------- | |
100 // The raw monitor subsystem is entirely distinct from normal | |
101 // java-synchronization or jni-synchronization. raw monitors are not | |
102 // associated with objects. They can be implemented in any manner | |
103 // that makes sense. The original implementors decided to piggy-back | |
104 // the raw-monitor implementation on the existing Java objectMonitor mechanism. | |
105 // This flaw needs to fixed. We should reimplement raw monitors as sui-generis. | |
106 // Specifically, we should not implement raw monitors via java monitors. | |
107 // Time permitting, we should disentangle and deconvolve the two implementations | |
108 // and move the resulting raw monitor implementation over to the JVMTI directories. | |
109 // Ideally, the raw monitor implementation would be built on top of | |
110 // park-unpark and nothing else. | |
111 // | |
112 // raw monitors are used mainly by JVMTI | |
113 // The raw monitor implementation borrows the ObjectMonitor structure, | |
114 // but the operators are degenerate and extremely simple. | |
115 // | |
116 // Mixed use of a single objectMonitor instance -- as both a raw monitor | |
117 // and a normal java monitor -- is not permissible. | |
118 // | |
119 // Note that we use the single RawMonitor_lock to protect queue operations for | |
120 // _all_ raw monitors. This is a scalability impediment, but since raw monitor usage | |
121 // is deprecated and rare, this is not of concern. The RawMonitor_lock can not | |
122 // be held indefinitely. The critical sections must be short and bounded. | |
123 // | |
124 // ------------------------------------------------------------------------- | |
125 | |
126 int JvmtiRawMonitor::SimpleEnter (Thread * Self) { | |
127 for (;;) { | |
128 if (Atomic::cmpxchg_ptr (Self, &_owner, NULL) == NULL) { | |
129 return OS_OK ; | |
130 } | |
131 | |
132 ObjectWaiter Node (Self) ; | |
133 Self->_ParkEvent->reset() ; // strictly optional | |
134 Node.TState = ObjectWaiter::TS_ENTER ; | |
135 | |
136 RawMonitor_lock->lock_without_safepoint_check() ; | |
137 Node._next = _EntryList ; | |
138 _EntryList = &Node ; | |
139 OrderAccess::fence() ; | |
140 if (_owner == NULL && Atomic::cmpxchg_ptr (Self, &_owner, NULL) == NULL) { | |
141 _EntryList = Node._next ; | |
142 RawMonitor_lock->unlock() ; | |
143 return OS_OK ; | |
144 } | |
145 RawMonitor_lock->unlock() ; | |
146 while (Node.TState == ObjectWaiter::TS_ENTER) { | |
147 Self->_ParkEvent->park() ; | |
148 } | |
149 } | |
150 } | |
151 | |
152 int JvmtiRawMonitor::SimpleExit (Thread * Self) { | |
153 guarantee (_owner == Self, "invariant") ; | |
154 OrderAccess::release_store_ptr (&_owner, NULL) ; | |
155 OrderAccess::fence() ; | |
156 if (_EntryList == NULL) return OS_OK ; | |
157 ObjectWaiter * w ; | |
158 | |
159 RawMonitor_lock->lock_without_safepoint_check() ; | |
160 w = _EntryList ; | |
161 if (w != NULL) { | |
162 _EntryList = w->_next ; | |
163 } | |
164 RawMonitor_lock->unlock() ; | |
165 if (w != NULL) { | |
166 guarantee (w ->TState == ObjectWaiter::TS_ENTER, "invariant") ; | |
167 ParkEvent * ev = w->_event ; | |
168 w->TState = ObjectWaiter::TS_RUN ; | |
169 OrderAccess::fence() ; | |
170 ev->unpark() ; | |
171 } | |
172 return OS_OK ; | |
173 } | |
174 | |
175 int JvmtiRawMonitor::SimpleWait (Thread * Self, jlong millis) { | |
176 guarantee (_owner == Self , "invariant") ; | |
177 guarantee (_recursions == 0, "invariant") ; | |
178 | |
179 ObjectWaiter Node (Self) ; | |
180 Node._notified = 0 ; | |
181 Node.TState = ObjectWaiter::TS_WAIT ; | |
182 | |
183 RawMonitor_lock->lock_without_safepoint_check() ; | |
184 Node._next = _WaitSet ; | |
185 _WaitSet = &Node ; | |
186 RawMonitor_lock->unlock() ; | |
187 | |
188 SimpleExit (Self) ; | |
189 guarantee (_owner != Self, "invariant") ; | |
190 | |
191 int ret = OS_OK ; | |
192 if (millis <= 0) { | |
193 Self->_ParkEvent->park(); | |
194 } else { | |
195 ret = Self->_ParkEvent->park(millis); | |
196 } | |
197 | |
198 // If thread still resides on the waitset then unlink it. | |
199 // Double-checked locking -- the usage is safe in this context | |
200 // as we TState is volatile and the lock-unlock operators are | |
201 // serializing (barrier-equivalent). | |
202 | |
203 if (Node.TState == ObjectWaiter::TS_WAIT) { | |
204 RawMonitor_lock->lock_without_safepoint_check() ; | |
205 if (Node.TState == ObjectWaiter::TS_WAIT) { | |
206 // Simple O(n) unlink, but performance isn't critical here. | |
207 ObjectWaiter * p ; | |
208 ObjectWaiter * q = NULL ; | |
209 for (p = _WaitSet ; p != &Node; p = p->_next) { | |
210 q = p ; | |
211 } | |
212 guarantee (p == &Node, "invariant") ; | |
213 if (q == NULL) { | |
214 guarantee (p == _WaitSet, "invariant") ; | |
215 _WaitSet = p->_next ; | |
216 } else { | |
217 guarantee (p == q->_next, "invariant") ; | |
218 q->_next = p->_next ; | |
219 } | |
220 Node.TState = ObjectWaiter::TS_RUN ; | |
221 } | |
222 RawMonitor_lock->unlock() ; | |
223 } | |
224 | |
225 guarantee (Node.TState == ObjectWaiter::TS_RUN, "invariant") ; | |
226 SimpleEnter (Self) ; | |
227 | |
228 guarantee (_owner == Self, "invariant") ; | |
229 guarantee (_recursions == 0, "invariant") ; | |
230 return ret ; | |
231 } | |
232 | |
233 int JvmtiRawMonitor::SimpleNotify (Thread * Self, bool All) { | |
234 guarantee (_owner == Self, "invariant") ; | |
235 if (_WaitSet == NULL) return OS_OK ; | |
236 | |
237 // We have two options: | |
238 // A. Transfer the threads from the WaitSet to the EntryList | |
239 // B. Remove the thread from the WaitSet and unpark() it. | |
240 // | |
241 // We use (B), which is crude and results in lots of futile | |
242 // context switching. In particular (B) induces lots of contention. | |
243 | |
244 ParkEvent * ev = NULL ; // consider using a small auto array ... | |
245 RawMonitor_lock->lock_without_safepoint_check() ; | |
246 for (;;) { | |
247 ObjectWaiter * w = _WaitSet ; | |
248 if (w == NULL) break ; | |
249 _WaitSet = w->_next ; | |
250 if (ev != NULL) { ev->unpark(); ev = NULL; } | |
251 ev = w->_event ; | |
252 OrderAccess::loadstore() ; | |
253 w->TState = ObjectWaiter::TS_RUN ; | |
254 OrderAccess::storeload(); | |
255 if (!All) break ; | |
256 } | |
257 RawMonitor_lock->unlock() ; | |
258 if (ev != NULL) ev->unpark(); | |
259 return OS_OK ; | |
260 } | |
261 | |
262 // Any JavaThread will enter here with state _thread_blocked | |
263 int JvmtiRawMonitor::raw_enter(TRAPS) { | |
264 TEVENT (raw_enter) ; | |
265 void * Contended ; | |
266 | |
267 // don't enter raw monitor if thread is being externally suspended, it will | |
268 // surprise the suspender if a "suspended" thread can still enter monitor | |
269 JavaThread * jt = (JavaThread *)THREAD; | |
270 if (THREAD->is_Java_thread()) { | |
271 jt->SR_lock()->lock_without_safepoint_check(); | |
272 while (jt->is_external_suspend()) { | |
273 jt->SR_lock()->unlock(); | |
274 jt->java_suspend_self(); | |
275 jt->SR_lock()->lock_without_safepoint_check(); | |
276 } | |
277 // guarded by SR_lock to avoid racing with new external suspend requests. | |
278 Contended = Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) ; | |
279 jt->SR_lock()->unlock(); | |
280 } else { | |
281 Contended = Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) ; | |
282 } | |
283 | |
284 if (Contended == THREAD) { | |
285 _recursions ++ ; | |
286 return OM_OK ; | |
287 } | |
288 | |
289 if (Contended == NULL) { | |
290 guarantee (_owner == THREAD, "invariant") ; | |
291 guarantee (_recursions == 0, "invariant") ; | |
292 return OM_OK ; | |
293 } | |
294 | |
295 THREAD->set_current_pending_monitor(this); | |
296 | |
297 if (!THREAD->is_Java_thread()) { | |
298 // No other non-Java threads besides VM thread would acquire | |
299 // a raw monitor. | |
300 assert(THREAD->is_VM_thread(), "must be VM thread"); | |
301 SimpleEnter (THREAD) ; | |
302 } else { | |
303 guarantee (jt->thread_state() == _thread_blocked, "invariant") ; | |
304 for (;;) { | |
305 jt->set_suspend_equivalent(); | |
306 // cleared by handle_special_suspend_equivalent_condition() or | |
307 // java_suspend_self() | |
308 SimpleEnter (THREAD) ; | |
309 | |
310 // were we externally suspended while we were waiting? | |
311 if (!jt->handle_special_suspend_equivalent_condition()) break ; | |
312 | |
313 // This thread was externally suspended | |
314 // | |
315 // This logic isn't needed for JVMTI raw monitors, | |
316 // but doesn't hurt just in case the suspend rules change. This | |
317 // logic is needed for the JvmtiRawMonitor.wait() reentry phase. | |
318 // We have reentered the contended monitor, but while we were | |
319 // waiting another thread suspended us. We don't want to reenter | |
320 // the monitor while suspended because that would surprise the | |
321 // thread that suspended us. | |
322 // | |
323 // Drop the lock - | |
324 SimpleExit (THREAD) ; | |
325 | |
326 jt->java_suspend_self(); | |
327 } | |
328 | |
329 assert(_owner == THREAD, "Fatal error with monitor owner!"); | |
330 assert(_recursions == 0, "Fatal error with monitor recursions!"); | |
331 } | |
332 | |
333 THREAD->set_current_pending_monitor(NULL); | |
334 guarantee (_recursions == 0, "invariant") ; | |
335 return OM_OK; | |
336 } | |
337 | |
338 // Used mainly for JVMTI raw monitor implementation | |
339 // Also used for JvmtiRawMonitor::wait(). | |
340 int JvmtiRawMonitor::raw_exit(TRAPS) { | |
341 TEVENT (raw_exit) ; | |
342 if (THREAD != _owner) { | |
343 return OM_ILLEGAL_MONITOR_STATE; | |
344 } | |
345 if (_recursions > 0) { | |
346 --_recursions ; | |
347 return OM_OK ; | |
348 } | |
349 | |
350 void * List = _EntryList ; | |
351 SimpleExit (THREAD) ; | |
352 | |
353 return OM_OK; | |
354 } | |
355 | |
356 // Used for JVMTI raw monitor implementation. | |
357 // All JavaThreads will enter here with state _thread_blocked | |
358 | |
359 int JvmtiRawMonitor::raw_wait(jlong millis, bool interruptible, TRAPS) { | |
360 TEVENT (raw_wait) ; | |
361 if (THREAD != _owner) { | |
362 return OM_ILLEGAL_MONITOR_STATE; | |
363 } | |
364 | |
365 // To avoid spurious wakeups we reset the parkevent -- This is strictly optional. | |
366 // The caller must be able to tolerate spurious returns from raw_wait(). | |
367 THREAD->_ParkEvent->reset() ; | |
368 OrderAccess::fence() ; | |
369 | |
370 // check interrupt event | |
371 if (interruptible && Thread::is_interrupted(THREAD, true)) { | |
372 return OM_INTERRUPTED; | |
373 } | |
374 | |
375 intptr_t save = _recursions ; | |
376 _recursions = 0 ; | |
377 _waiters ++ ; | |
378 if (THREAD->is_Java_thread()) { | |
379 guarantee (((JavaThread *) THREAD)->thread_state() == _thread_blocked, "invariant") ; | |
380 ((JavaThread *)THREAD)->set_suspend_equivalent(); | |
381 } | |
382 int rv = SimpleWait (THREAD, millis) ; | |
383 _recursions = save ; | |
384 _waiters -- ; | |
385 | |
386 guarantee (THREAD == _owner, "invariant") ; | |
387 if (THREAD->is_Java_thread()) { | |
388 JavaThread * jSelf = (JavaThread *) THREAD ; | |
389 for (;;) { | |
390 if (!jSelf->handle_special_suspend_equivalent_condition()) break ; | |
391 SimpleExit (THREAD) ; | |
392 jSelf->java_suspend_self(); | |
393 SimpleEnter (THREAD) ; | |
394 jSelf->set_suspend_equivalent() ; | |
395 } | |
396 } | |
397 guarantee (THREAD == _owner, "invariant") ; | |
398 | |
399 if (interruptible && Thread::is_interrupted(THREAD, true)) { | |
400 return OM_INTERRUPTED; | |
401 } | |
402 return OM_OK ; | |
403 } | |
404 | |
405 int JvmtiRawMonitor::raw_notify(TRAPS) { | |
406 TEVENT (raw_notify) ; | |
407 if (THREAD != _owner) { | |
408 return OM_ILLEGAL_MONITOR_STATE; | |
409 } | |
410 SimpleNotify (THREAD, false) ; | |
411 return OM_OK; | |
412 } | |
413 | |
414 int JvmtiRawMonitor::raw_notifyAll(TRAPS) { | |
415 TEVENT (raw_notifyAll) ; | |
416 if (THREAD != _owner) { | |
417 return OM_ILLEGAL_MONITOR_STATE; | |
418 } | |
419 SimpleNotify (THREAD, true) ; | |
420 return OM_OK; | |
421 } | |
422 |