src/share/vm/runtime/mutex.cpp
Print this page
rev 6249 : 8039458: Ensure consistency of Monitor/Mutex lock acquisitions in relation to safepoint protocol
Reviewed-by:
*** 898,907 ****
--- 898,908 ----
if (TryFast()) {
Exeunt:
assert (ILocked(), "invariant") ;
assert (owner() == NULL, "invariant");
+ debug_only(_acquired_with_no_safepoint_check = false;)
set_owner (Self);
return ;
}
// The lock is contended ...
*** 943,952 ****
--- 944,954 ----
void Monitor::lock_without_safepoint_check (Thread * Self) {
assert (_owner != Self, "invariant") ;
ILock (Self) ;
assert (_owner == NULL, "invariant");
+ debug_only(_acquired_with_no_safepoint_check = true;)
set_owner (Self);
}
void Monitor::lock_without_safepoint_check () {
lock_without_safepoint_check (Thread::current()) ;
*** 981,990 ****
--- 983,993 ----
}
void Monitor::unlock() {
assert (_owner == Thread::current(), "invariant") ;
assert (_OnDeck != Thread::current()->_MutexEvent , "invariant") ;
+ debug_only(_acquired_with_no_safepoint_check = false);
set_owner (NULL) ;
if (_snuck) {
assert(SafepointSynchronize::is_at_safepoint() && Thread::current()->is_VM_thread(), "sneak");
_snuck = false;
return ;
*** 1150,1159 ****
--- 1153,1163 ----
m->_LockWord.FullWord = 0 ;
m->_EntryList = NULL ;
m->_OnDeck = NULL ;
m->_WaitSet = NULL ;
m->_WaitLock[0] = 0 ;
+ debug_only(m->_acquired_with_no_safepoint_check = false);
}
Monitor::Monitor() { ClearMonitor(this); }
Monitor::Monitor (int Rank, const char * name, bool allow_vm_block) {
*** 1306,1315 ****
--- 1310,1321 ----
fatal(err_msg("acquiring lock %s/%d out of order with lock %s/%d -- "
"possible deadlock", this->name(), this->rank(),
locks->name(), locks->rank()));
}
+ debug_only(ensure_lock_acquisition_consistency(new_owner);)
+
this->_next = new_owner->_owned_locks;
new_owner->_owned_locks = this;
#endif
} else {
*** 1345,1354 ****
--- 1351,1407 ----
_next = NULL;
#endif
}
}
+ /*
+ * Ensure consistency of Monitor/Mutex lock acquisitions
+ * for Java Threads running inside the VM.
+ *
+ * If a thread has already acquired lock(s) using
+ * "Mutex::_no_safepoint_check_flag" (effectively going outside the
+ * safepoint protocol), the thread should be disallowed to acquire any
+ * additional lock which _is_ participating in the safepoint protocol.
+ *
+ * If a "safepoint protocol aware" lock is contended, and the thread entering
+ * is unable to "fast acquire" the lock using cas/try_spin,
+ * it will need to block/park. Blocking on a contended lock involves a
+ * state transition and a potential SafepointSynchronize::block() call.
+ * Transitioning to a blocked state still holding "Mutex::_no_safepoint_check_flag"
+ * acquired locks is allowed, but is *very* deadlock prone.
+ *
+ * The effect of allowing this state to happen without checking is subtle
+ * and hard to debug since a problem might only appear under heavy load and
+ * only in situations with increased concurrency levels (product builds).
+ *
+ * This function will preempt this problematic state for earlier deadlock detection.
+ */
+ void Monitor::ensure_lock_acquisition_consistency(const Thread* new_owner) const {
+ if (new_owner != NULL && new_owner->is_Java_thread()) {
+ const Monitor* const locks = new_owner->owned_locks();
+ if (locks != NULL) {
+ if (!acquired_with_no_safepoint_check()) {
+ if (locks->acquired_with_no_safepoint_check()) {
+ new_owner->print_owned_locks();
+ fatal(err_msg("Acquiring lock (%s) might "
+ "cause the thread to block.\n"
+ "The thread is also the owner "
+ "of a lock previously taken using "
+ "Mutex::_no_safepoint_check_flag (%s).\n"
+ "This pattern is not allowed since "
+ "it is *very* deadlock prone!",
+ this->name(),
+ locks->name()));
+ }
+ }
+ }
+ }
+ }
+
+ bool Monitor::acquired_with_no_safepoint_check(void) const {
+ return _acquired_with_no_safepoint_check;
+ }
// Factored out common sanity checks for locking mutex'es. Used by lock() and try_lock()
void Monitor::check_prelock_state(Thread *thread) {
assert((!thread->is_Java_thread() || ((JavaThread *)thread)->thread_state() == _thread_in_vm)
|| rank() == Mutex::special, "wrong thread state for using locks");