@@ -43,10 +43,12 @@ void JvmtiPendingMonitors::transition_raw_monitors() {
43
43
" Java thread has not been created yet or more than one java thread "
44
44
" is running. Raw monitor transition will not work" );
45
45
JavaThread* current_java_thread = JavaThread::current ();
46
- assert (current_java_thread->thread_state () == _thread_in_vm, " Must be in vm" );
47
- for (int i = 0 ; i < count (); i++) {
48
- JvmtiRawMonitor* rmonitor = monitors ()->at (i);
49
- rmonitor->raw_enter (current_java_thread);
46
+ {
47
+ ThreadToNativeFromVM ttnfvm (current_java_thread);
48
+ for (int i = 0 ; i < count (); i++) {
49
+ JvmtiRawMonitor* rmonitor = monitors ()->at (i);
50
+ rmonitor->raw_enter (current_java_thread);
51
+ }
50
52
}
51
53
// pending monitors are converted to real monitor so delete them all.
52
54
dispose ();
@@ -60,7 +62,6 @@ JvmtiRawMonitor::JvmtiRawMonitor(const char* name) : _owner(NULL),
60
62
_recursions(0 ),
61
63
_entry_list(NULL ),
62
64
_wait_set(NULL ),
63
- _waiters(0 ),
64
65
_magic(JVMTI_RM_MAGIC),
65
66
_name(NULL ) {
66
67
#ifdef ASSERT
@@ -217,11 +218,12 @@ inline void JvmtiRawMonitor::dequeue_waiter(QNode& node) {
217
218
// simple_wait is not quite so simple as we have to deal with the interaction
218
219
// with the Thread interrupt state, which resides in the java.lang.Thread object.
219
220
// That state must only be accessed while _thread_in_vm and requires proper thread-state
220
- // transitions. However, we cannot perform such transitions whilst we hold the RawMonitor,
221
- // else we can deadlock with the VMThread (which may also use RawMonitors as part of
222
- // executing various callbacks).
221
+ // transitions.
223
222
// Returns M_OK usually, but M_INTERRUPTED if the thread is a JavaThread and was
224
223
// interrupted.
224
+ // Note:
225
+ // - simple_wait never reenters the monitor.
226
+ // - A JavaThread must be in native.
225
227
int JvmtiRawMonitor::simple_wait (Thread* self, jlong millis) {
226
228
guarantee (_owner == self , " invariant" );
227
229
guarantee (_recursions == 0 , " invariant" );
@@ -235,21 +237,24 @@ int JvmtiRawMonitor::simple_wait(Thread* self, jlong millis) {
235
237
int ret = M_OK;
236
238
if (self->is_Java_thread ()) {
237
239
JavaThread* jt = self->as_Java_thread ();
238
- // Transition to VM so we can check interrupt state
239
- ThreadInVMfromNative tivm (jt);
240
- if (jt->is_interrupted (true )) {
240
+ guarantee (jt->thread_state () == _thread_in_native, " invariant" );
241
+ {
242
+ // This transition must be after we exited the monitor.
243
+ ThreadInVMfromNative tivmfn (jt);
244
+ if (jt->is_interrupted (true )) {
241
245
ret = M_INTERRUPTED;
242
- } else {
243
- ThreadBlockInVM tbivm (jt);
244
- if (millis <= 0 ) {
245
- self->_ParkEvent ->park ();
246
246
} else {
247
- self->_ParkEvent ->park (millis);
247
+ ThreadBlockInVM tbivm (jt);
248
+ if (millis <= 0 ) {
249
+ self->_ParkEvent ->park ();
250
+ } else {
251
+ self->_ParkEvent ->park (millis);
252
+ }
253
+ // Return to VM before post-check of interrupt state
254
+ }
255
+ if (jt->is_interrupted (true )) {
256
+ ret = M_INTERRUPTED;
248
257
}
249
- // Return to VM before post-check of interrupt state
250
- }
251
- if (jt->is_interrupted (true )) {
252
- ret = M_INTERRUPTED;
253
258
}
254
259
} else {
255
260
if (millis <= 0 ) {
@@ -261,10 +266,6 @@ int JvmtiRawMonitor::simple_wait(Thread* self, jlong millis) {
261
266
262
267
dequeue_waiter (node);
263
268
264
- simple_enter (self);
265
- guarantee (_owner == self, " invariant" );
266
- guarantee (_recursions == 0 , " invariant" );
267
-
268
269
return ret;
269
270
}
270
271
@@ -306,75 +307,37 @@ void JvmtiRawMonitor::simple_notify(Thread* self, bool all) {
306
307
return ;
307
308
}
308
309
309
- // Any JavaThread will enter here with state _thread_blocked unless we
310
- // are in single-threaded mode during startup.
311
- void JvmtiRawMonitor::raw_enter (Thread* self) {
312
- void * contended;
313
- JavaThread* jt = NULL ;
314
- // don't enter raw monitor if thread is being externally suspended, it will
315
- // surprise the suspender if a "suspended" thread can still enter monitor
316
- if (self->is_Java_thread ()) {
317
- jt = self->as_Java_thread ();
318
- while (true ) {
319
- // To pause suspend requests while in blocked we must block handshakes.
320
- jt->handshake_state ()->lock ();
321
- // Suspend request flag can only be set in handshakes.
322
- // By blocking handshakes, suspend request flag cannot change its value.
323
- if (!jt->handshake_state ()->is_suspended ()) {
324
- contended = Atomic::cmpxchg (&_owner, (Thread*)NULL , jt);
325
- jt->handshake_state ()->unlock ();
326
- break ;
327
- }
328
- jt->handshake_state ()->unlock ();
329
-
330
- // We may only be in states other than _thread_blocked when we are
331
- // in single-threaded mode during startup.
332
- guarantee (jt->thread_state () == _thread_blocked, " invariant" );
333
-
334
- jt->set_thread_state_fence (_thread_blocked_trans);
335
- SafepointMechanism::process_if_requested (jt);
336
- // We should transition to thread_in_vm and then to thread_in_vm_trans,
337
- // but those are always treated the same as _thread_blocked_trans.
338
- jt->set_thread_state (_thread_blocked);
339
- }
340
- } else {
341
- contended = Atomic::cmpxchg (&_owner, (Thread*)NULL , self);
342
- }
310
+ void JvmtiRawMonitor::ExitOnSuspend::operator ()(JavaThread* current) {
311
+ // We must exit the monitor in case of a safepoint.
312
+ _rm->simple_exit (current);
313
+ _rm_exited = true ;
314
+ }
343
315
344
- if (contended == self) {
316
+ // JavaThreads will enter here with state _thread_in_native.
317
+ void JvmtiRawMonitor::raw_enter (Thread* self) {
318
+ // TODO Atomic::load on _owner field
319
+ if (_owner == self) {
345
320
_recursions++;
346
321
return ;
347
322
}
348
323
349
- if (contended == NULL ) {
350
- guarantee (_owner == self, " invariant" );
351
- guarantee (_recursions == 0 , " invariant" );
352
- return ;
353
- }
354
-
355
324
self->set_current_pending_raw_monitor (this );
356
325
357
326
if (!self->is_Java_thread ()) {
358
327
simple_enter (self);
359
328
} else {
360
- // In multi-threaded mode, we must enter this method blocked.
361
- guarantee (jt->thread_state () == _thread_blocked, " invariant" );
329
+ JavaThread* jt = self->as_Java_thread ();
330
+ guarantee (jt->thread_state () == _thread_in_native, " invariant" );
331
+ ThreadInVMfromNative tivmfn (jt);
362
332
for (;;) {
363
- simple_enter (jt );
364
- if (! SafepointMechanism::should_process (jt)) {
365
- // Not suspended so we're done here.
366
- break ;
333
+ ExitOnSuspend eos ( this );
334
+ {
335
+ ThreadBlockInVMPreprocess<ExitOnSuspend> tbivmp (jt, eos);
336
+ simple_enter (jt) ;
367
337
}
368
- if (!jt->is_suspended ()) {
369
- // Not suspended so we're done here.
338
+ if (!eos.monitor_exited ()) {
370
339
break ;
371
340
}
372
- simple_exit (jt);
373
- jt->set_thread_state_fence (_thread_blocked_trans);
374
- SafepointMechanism::process_if_requested (jt);
375
- // We should transition to thread_in_vm and then to thread_in_vm_trans,
376
- // but those are always treated the same as _thread_blocked_trans.
377
- jt->set_thread_state (_thread_blocked);
378
341
}
379
342
}
380
343
@@ -411,37 +374,34 @@ int JvmtiRawMonitor::raw_wait(jlong millis, Thread* self) {
411
374
412
375
intptr_t save = _recursions;
413
376
_recursions = 0 ;
414
- _waiters++;
415
377
ret = simple_wait (self, millis);
416
- _recursions = save;
417
- _waiters--;
418
-
419
- guarantee (self == _owner, " invariant" );
420
378
421
- if (self->is_Java_thread ()) {
379
+ // Now we need to re-enter the monitor. For JavaThreads
380
+ // we need to manage suspend requests.
381
+ if (self->is_Java_thread ()) { // JavaThread re-enter
422
382
JavaThread* jt = self->as_Java_thread ();
423
- guarantee (jt-> thread_state () == _thread_in_native, " invariant " );
383
+ ThreadInVMfromNative tivmfn (jt);
424
384
for (;;) {
425
- if (!SafepointMechanism::should_process (jt)) {
426
- // Not suspended so we're done here:
427
- break ;
385
+ ExitOnSuspend eos (this );
386
+ {
387
+ ThreadBlockInVMPreprocess<ExitOnSuspend> tbivmp (jt, eos);
388
+ simple_enter (jt);
428
389
}
429
- simple_exit (jt);
430
- jt->set_thread_state_fence (_thread_in_native_trans);
431
- SafepointMechanism::process_if_requested (jt);
432
- if (jt->is_interrupted (true )) {
433
- ret = M_INTERRUPTED;
390
+ if (!eos.monitor_exited ()) {
391
+ break ;
434
392
}
435
- // We should transition to thread_in_vm and then to thread_in_vm_trans,
436
- // but those are always treated the same as _thread_in_native_trans.
437
- jt->set_thread_state (_thread_in_native);
438
- simple_enter (jt);
439
393
}
440
- guarantee (jt == _owner, " invariant" );
441
- } else {
394
+ if (jt->is_interrupted (true )) {
395
+ ret = M_INTERRUPTED;
396
+ }
397
+ } else { // Non-JavaThread re-enter
442
398
assert (ret != M_INTERRUPTED, " Only JavaThreads can be interrupted" );
399
+ simple_enter (self);
443
400
}
444
401
402
+ _recursions = save;
403
+
404
+ guarantee (self == _owner, " invariant" );
445
405
return ret;
446
406
}
447
407
0 commit comments