8255678: Add Mutex::try_lock version without rank checks
Reviewed-by: dcubed, dholmes, coleenp
This commit is contained in:
parent
884b9ff24f
commit
aabc9ca266
@ -100,10 +100,11 @@ void Mutex::lock_contended(Thread* self) {
|
||||
}
|
||||
|
||||
void Mutex::lock(Thread* self) {
|
||||
check_safepoint_state(self);
|
||||
|
||||
assert(_owner != self, "invariant");
|
||||
|
||||
check_safepoint_state(self);
|
||||
check_rank(self);
|
||||
|
||||
if (!_lock.try_lock()) {
|
||||
// The lock is contended, use contended slow-path function to lock
|
||||
lock_contended(self);
|
||||
@ -124,8 +125,11 @@ void Mutex::lock() {
|
||||
// in the wrong way this can lead to a deadlock with the safepoint code.
|
||||
|
||||
void Mutex::lock_without_safepoint_check(Thread * self) {
|
||||
check_no_safepoint_state(self);
|
||||
assert(_owner != self, "invariant");
|
||||
|
||||
check_no_safepoint_state(self);
|
||||
check_rank(self);
|
||||
|
||||
_lock.lock();
|
||||
assert_owner(NULL);
|
||||
set_owner(self);
|
||||
@ -137,14 +141,22 @@ void Mutex::lock_without_safepoint_check() {
|
||||
|
||||
|
||||
// Returns true if thread succeeds in grabbing the lock, otherwise false.
|
||||
bool Mutex::try_lock() {
|
||||
bool Mutex::try_lock_inner(bool do_rank_checks) {
|
||||
Thread * const self = Thread::current();
|
||||
// Checking the owner hides the potential difference in recursive locking behaviour
|
||||
// on some platforms.
|
||||
if (_owner == self) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (do_rank_checks) {
|
||||
check_rank(self);
|
||||
}
|
||||
// Some safepoint_check_always locks use try_lock, so cannot check
|
||||
// safepoint state, but can check blocking state.
|
||||
check_block_state(self);
|
||||
// Checking the owner hides the potential difference in recursive locking behaviour
|
||||
// on some platforms.
|
||||
if (_owner != self && _lock.try_lock()) {
|
||||
|
||||
if (_lock.try_lock()) {
|
||||
assert_owner(NULL);
|
||||
set_owner(self);
|
||||
return true;
|
||||
@ -152,6 +164,16 @@ bool Mutex::try_lock() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Mutex::try_lock() {
|
||||
return try_lock_inner(true /* do_rank_checks */);
|
||||
}
|
||||
|
||||
bool Mutex::try_lock_without_rank_check() {
|
||||
bool res = try_lock_inner(false /* do_rank_checks */);
|
||||
DEBUG_ONLY(if (res) _skip_rank_check = true;)
|
||||
return res;
|
||||
}
|
||||
|
||||
void Mutex::release_for_safepoint() {
|
||||
assert_owner(NULL);
|
||||
_lock.unlock();
|
||||
@ -173,31 +195,18 @@ void Monitor::notify_all() {
|
||||
_lock.notify_all();
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
void Monitor::assert_wait_lock_state(Thread* self) {
|
||||
Mutex* least = get_least_ranked_lock_besides_this(self->owned_locks());
|
||||
assert(least != this, "Specification of get_least_... call above");
|
||||
if (least != NULL && least->rank() <= special) {
|
||||
::tty->print("Attempting to wait on monitor %s/%d while holding"
|
||||
" lock %s/%d -- possible deadlock",
|
||||
name(), rank(), least->name(), least->rank());
|
||||
assert(false, "Shouldn't block(wait) while holding a lock of rank special");
|
||||
}
|
||||
}
|
||||
#endif // ASSERT
|
||||
|
||||
bool Monitor::wait_without_safepoint_check(int64_t timeout) {
|
||||
Thread* const self = Thread::current();
|
||||
|
||||
// timeout is in milliseconds - with zero meaning never timeout
|
||||
assert(timeout >= 0, "negative timeout");
|
||||
|
||||
assert_owner(self);
|
||||
assert_wait_lock_state(self);
|
||||
check_rank(self);
|
||||
|
||||
// conceptually set the owner to NULL in anticipation of
|
||||
// abdicating the lock in wait
|
||||
set_owner(NULL);
|
||||
|
||||
// Check safepoint state after resetting owner and possible NSV.
|
||||
check_no_safepoint_state(self);
|
||||
|
||||
@ -208,23 +217,22 @@ bool Monitor::wait_without_safepoint_check(int64_t timeout) {
|
||||
|
||||
bool Monitor::wait(int64_t timeout, bool as_suspend_equivalent) {
|
||||
JavaThread* const self = JavaThread::current();
|
||||
// Safepoint checking logically implies an active JavaThread.
|
||||
assert(self->is_active_Java_thread(), "invariant");
|
||||
|
||||
// timeout is in milliseconds - with zero meaning never timeout
|
||||
assert(timeout >= 0, "negative timeout");
|
||||
|
||||
assert_owner(self);
|
||||
check_rank(self);
|
||||
|
||||
// Safepoint checking logically implies an active JavaThread.
|
||||
guarantee(self->is_active_Java_thread(), "invariant");
|
||||
assert_wait_lock_state(self);
|
||||
|
||||
int wait_status;
|
||||
// conceptually set the owner to NULL in anticipation of
|
||||
// abdicating the lock in wait
|
||||
set_owner(NULL);
|
||||
|
||||
// Check safepoint state after resetting owner and possible NSV.
|
||||
check_safepoint_state(self);
|
||||
|
||||
int wait_status;
|
||||
Mutex* in_flight_mutex = NULL;
|
||||
|
||||
{
|
||||
@ -285,6 +293,7 @@ Mutex::Mutex(int Rank, const char * name, bool allow_vm_block,
|
||||
_allow_vm_block = allow_vm_block;
|
||||
_rank = Rank;
|
||||
_safepoint_check_required = safepoint_check_required;
|
||||
_skip_rank_check = false;
|
||||
|
||||
assert(_safepoint_check_required != _safepoint_check_sometimes || is_sometimes_ok(name),
|
||||
"Lock has _safepoint_check_sometimes %s", name);
|
||||
@ -330,7 +339,7 @@ void Mutex::print_on(outputStream* st) const {
|
||||
st->print(" %s", print_safepoint_check(_safepoint_check_required));
|
||||
st->cr();
|
||||
}
|
||||
#endif
|
||||
#endif // PRODUCT
|
||||
|
||||
#ifdef ASSERT
|
||||
void Mutex::assert_owner(Thread * expected) {
|
||||
@ -353,16 +362,6 @@ Mutex* Mutex::get_least_ranked_lock(Mutex* locks) {
|
||||
res = tmp;
|
||||
}
|
||||
}
|
||||
if (!SafepointSynchronize::is_at_safepoint()) {
|
||||
// In this case, we expect the held locks to be
|
||||
// in increasing rank order (modulo any native ranks)
|
||||
for (tmp = locks; tmp != NULL; tmp = tmp->next()) {
|
||||
if (tmp->next() != NULL) {
|
||||
assert(tmp->rank() == Mutex::native ||
|
||||
tmp->rank() <= tmp->next()->rank(), "mutex rank anomaly?");
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -373,17 +372,56 @@ Mutex* Mutex::get_least_ranked_lock_besides_this(Mutex* locks) {
|
||||
res = tmp;
|
||||
}
|
||||
}
|
||||
assert(res != this, "invariant");
|
||||
return res;
|
||||
}
|
||||
|
||||
// Tests for rank violations that might indicate exposure to deadlock.
|
||||
void Mutex::check_rank(Thread* thread) {
|
||||
assert(this->rank() >= 0, "bad lock rank");
|
||||
Mutex* locks_owned = thread->owned_locks();
|
||||
|
||||
if (!SafepointSynchronize::is_at_safepoint()) {
|
||||
// In this case, we expect the held locks to be
|
||||
// in increasing rank order (modulo any native ranks)
|
||||
for (tmp = locks; tmp != NULL; tmp = tmp->next()) {
|
||||
// We expect the locks already acquired to be in increasing rank order,
|
||||
// modulo locks of native rank or acquired in try_lock_without_rank_check()
|
||||
for (Mutex* tmp = locks_owned; tmp != NULL; tmp = tmp->next()) {
|
||||
if (tmp->next() != NULL) {
|
||||
assert(tmp->rank() == Mutex::native ||
|
||||
tmp->rank() <= tmp->next()->rank(), "mutex rank anomaly?");
|
||||
assert(tmp->rank() == Mutex::native || tmp->rank() < tmp->next()->rank()
|
||||
|| tmp->skip_rank_check(), "mutex rank anomaly?");
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
|
||||
// Locks with rank native or suspend_resume are an exception and are not
|
||||
// subject to the verification rules.
|
||||
bool check_can_be_skipped = this->rank() == Mutex::native || this->rank() == Mutex::suspend_resume
|
||||
|| SafepointSynchronize::is_at_safepoint();
|
||||
if (owned_by_self()) {
|
||||
// wait() case
|
||||
Mutex* least = get_least_ranked_lock_besides_this(locks_owned);
|
||||
// We enforce not holding locks of rank special or lower while waiting.
|
||||
// Also "this" should be the monitor with lowest rank owned by this thread.
|
||||
if (least != NULL && (least->rank() <= special ||
|
||||
(least->rank() <= this->rank() && !check_can_be_skipped))) {
|
||||
assert(false, "Attempting to wait on monitor %s/%d while holding lock %s/%d -- "
|
||||
"possible deadlock. %s", name(), rank(), least->name(), least->rank(),
|
||||
least->rank() <= this->rank() ? "Should wait on the least ranked monitor from "
|
||||
"all owned locks." : "Should not block(wait) while holding a lock of rank special.");
|
||||
}
|
||||
} else if (!check_can_be_skipped) {
|
||||
// lock()/lock_without_safepoint_check()/try_lock() case
|
||||
Mutex* least = get_least_ranked_lock(locks_owned);
|
||||
// Deadlock prevention rules require us to acquire Mutexes only in
|
||||
// a global total order. For example, if m1 is the lowest ranked mutex
|
||||
// that the thread holds and m2 is the mutex the thread is trying
|
||||
// to acquire, then deadlock prevention rules require that the rank
|
||||
// of m2 be less than the rank of m1. This prevents circular waits.
|
||||
if (least != NULL && least->rank() <= this->rank()) {
|
||||
thread->print_owned_locks();
|
||||
assert(false, "Attempting to acquire lock %s/%d out of order with lock %s/%d -- "
|
||||
"possible deadlock", this->name(), this->rank(), least->name(), least->rank());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Mutex::contains(Mutex* locks, Mutex* lock) {
|
||||
@ -413,8 +451,7 @@ void Mutex::no_safepoint_verifier(Thread* thread, bool enable) {
|
||||
}
|
||||
|
||||
// Called immediately after lock acquisition or release as a diagnostic
|
||||
// to track the lock-set of the thread and test for rank violations that
|
||||
// might indicate exposure to deadlock.
|
||||
// to track the lock-set of the thread.
|
||||
// Rather like an EventListener for _owner (:>).
|
||||
|
||||
void Mutex::set_owner_implementation(Thread *new_owner) {
|
||||
@ -436,29 +473,6 @@ void Mutex::set_owner_implementation(Thread *new_owner) {
|
||||
_owner = new_owner; // set the owner
|
||||
|
||||
// link "this" into the owned locks list
|
||||
|
||||
Mutex* locks = get_least_ranked_lock(new_owner->owned_locks());
|
||||
// Mutex::set_owner_implementation is a friend of Thread
|
||||
|
||||
assert(this->rank() >= 0, "bad lock rank");
|
||||
|
||||
// Deadlock avoidance rules require us to acquire Mutexes only in
|
||||
// a global total order. For example m1 is the lowest ranked mutex
|
||||
// that the thread holds and m2 is the mutex the thread is trying
|
||||
// to acquire, then deadlock avoidance rules require that the rank
|
||||
// of m2 be less than the rank of m1.
|
||||
// The rank Mutex::native is an exception in that it is not subject
|
||||
// to the verification rules.
|
||||
if (this->rank() != Mutex::native &&
|
||||
this->rank() != Mutex::suspend_resume &&
|
||||
locks != NULL && locks->rank() <= this->rank() &&
|
||||
!SafepointSynchronize::is_at_safepoint()) {
|
||||
new_owner->print_owned_locks();
|
||||
fatal("acquiring lock %s/%d out of order with lock %s/%d -- "
|
||||
"possible deadlock", this->name(), this->rank(),
|
||||
locks->name(), locks->rank());
|
||||
}
|
||||
|
||||
this->_next = new_owner->_owned_locks;
|
||||
new_owner->_owned_locks = this;
|
||||
|
||||
@ -470,6 +484,7 @@ void Mutex::set_owner_implementation(Thread *new_owner) {
|
||||
|
||||
Thread* old_owner = _owner;
|
||||
_last_owner = old_owner;
|
||||
_skip_rank_check = false;
|
||||
|
||||
assert(old_owner != NULL, "removing the owner thread of an unowned mutex");
|
||||
assert(old_owner == Thread::current(), "removing the owner thread of an unowned mutex");
|
||||
|
@ -89,18 +89,33 @@ class Mutex : public CHeapObj<mtSynchronizer> {
|
||||
// Debugging fields for naming, deadlock detection, etc. (some only used in debug mode)
|
||||
#ifndef PRODUCT
|
||||
bool _allow_vm_block;
|
||||
#endif
|
||||
#ifdef ASSERT
|
||||
int _rank; // rank (to avoid/detect potential deadlocks)
|
||||
Mutex* _next; // Used by a Thread to link up owned locks
|
||||
Thread* _last_owner; // the last thread to own the lock
|
||||
bool _skip_rank_check; // read only by owner when doing rank checks
|
||||
|
||||
static bool contains(Mutex* locks, Mutex* lock);
|
||||
static Mutex* get_least_ranked_lock(Mutex* locks);
|
||||
Mutex* get_least_ranked_lock_besides_this(Mutex* locks);
|
||||
#endif // ASSERT
|
||||
bool skip_rank_check() {
|
||||
assert(owned_by_self(), "only the owner should call this");
|
||||
return _skip_rank_check;
|
||||
}
|
||||
|
||||
public:
|
||||
int rank() const { return _rank; }
|
||||
Mutex* next() const { return _next; }
|
||||
void set_next(Mutex *next) { _next = next; }
|
||||
#endif // ASSERT
|
||||
|
||||
protected:
|
||||
void set_owner_implementation(Thread* owner) NOT_DEBUG({ _owner = owner;});
|
||||
void check_block_state (Thread* thread) NOT_DEBUG_RETURN;
|
||||
void check_safepoint_state (Thread* thread) NOT_DEBUG_RETURN;
|
||||
void check_no_safepoint_state(Thread* thread) NOT_DEBUG_RETURN;
|
||||
void check_rank (Thread* thread) NOT_DEBUG_RETURN;
|
||||
void assert_owner (Thread* expected) NOT_DEBUG_RETURN;
|
||||
void no_safepoint_verifier (Thread* thread, bool enable) NOT_DEBUG_RETURN;
|
||||
|
||||
@ -170,6 +185,7 @@ class Mutex : public CHeapObj<mtSynchronizer> {
|
||||
bool try_lock(); // Like lock(), but unblocking. It returns false instead
|
||||
private:
|
||||
void lock_contended(Thread *thread); // contended slow-path
|
||||
bool try_lock_inner(bool do_rank_checks);
|
||||
public:
|
||||
|
||||
void release_for_safepoint();
|
||||
@ -178,33 +194,25 @@ class Mutex : public CHeapObj<mtSynchronizer> {
|
||||
// that is guaranteed not to block while running inside the VM.
|
||||
void lock_without_safepoint_check();
|
||||
void lock_without_safepoint_check(Thread* self);
|
||||
// A thread should not call this if failure to acquire ownership will blocks its progress
|
||||
bool try_lock_without_rank_check();
|
||||
|
||||
// Current owner - not not MT-safe. Can only be used to guarantee that
|
||||
// the current running thread owns the lock
|
||||
Thread* owner() const { return _owner; }
|
||||
void set_owner(Thread* owner) { set_owner_implementation(owner); }
|
||||
bool owned_by_self() const;
|
||||
|
||||
const char *name() const { return _name; }
|
||||
|
||||
void print_on_error(outputStream* st) const;
|
||||
|
||||
#ifndef PRODUCT
|
||||
void print_on(outputStream* st) const;
|
||||
void print() const { print_on(::tty); }
|
||||
#endif
|
||||
#ifdef ASSERT
|
||||
int rank() const { return _rank; }
|
||||
bool allow_vm_block() { return _allow_vm_block; }
|
||||
|
||||
Mutex *next() const { return _next; }
|
||||
void set_next(Mutex *next) { _next = next; }
|
||||
#endif // ASSERT
|
||||
|
||||
void set_owner(Thread* owner) { set_owner_implementation(owner); }
|
||||
};
|
||||
|
||||
class Monitor : public Mutex {
|
||||
void assert_wait_lock_state (Thread* self) NOT_DEBUG_RETURN;
|
||||
public:
|
||||
Monitor(int rank, const char *name, bool allow_vm_block = false,
|
||||
SafepointCheckRequired safepoint_check_required = _safepoint_check_always);
|
||||
|
168
test/hotspot/gtest/runtime/test_mutex_rank.cpp
Normal file
168
test/hotspot/gtest/runtime/test_mutex_rank.cpp
Normal file
@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "runtime/interfaceSupport.inline.hpp"
|
||||
#include "runtime/mutex.hpp"
|
||||
#include "runtime/mutexLocker.hpp"
|
||||
#include "unittest.hpp"
|
||||
|
||||
#ifdef ASSERT
|
||||
|
||||
const int rankA = 50;
|
||||
|
||||
TEST_OTHER_VM(MutexRank, mutex_lock_rank_in_order) {
|
||||
JavaThread* THREAD = JavaThread::current();
|
||||
ThreadInVMfromNative invm(THREAD);
|
||||
|
||||
Mutex* mutex_rankA = new Mutex(rankA, "mutex_rankA", false, Mutex::_safepoint_check_always);
|
||||
Mutex* mutex_rankA_plus_one = new Mutex(rankA + 1, "mutex_rankA_plus_one", false, Mutex::_safepoint_check_always);
|
||||
|
||||
mutex_rankA_plus_one->lock();
|
||||
mutex_rankA->lock();
|
||||
mutex_rankA->unlock();
|
||||
mutex_rankA_plus_one->unlock();
|
||||
}
|
||||
|
||||
TEST_VM_ASSERT_MSG(MutexRank, mutex_lock_rank_out_of_orderA,
|
||||
"Attempting to acquire lock mutex_rankA_plus_one/51 out of order with lock mutex_rankA/50 -- possible deadlock") {
|
||||
JavaThread* THREAD = JavaThread::current();
|
||||
ThreadInVMfromNative invm(THREAD);
|
||||
|
||||
Mutex* mutex_rankA = new Mutex(rankA, "mutex_rankA", false, Mutex::_safepoint_check_always);
|
||||
Mutex* mutex_rankA_plus_one = new Mutex(rankA + 1, "mutex_rankA_plus_one", false, Mutex::_safepoint_check_always);
|
||||
|
||||
mutex_rankA->lock();
|
||||
mutex_rankA_plus_one->lock();
|
||||
mutex_rankA_plus_one->unlock();
|
||||
mutex_rankA->unlock();
|
||||
}
|
||||
|
||||
TEST_VM_ASSERT_MSG(MutexRank, mutex_lock_rank_out_of_orderB,
|
||||
"Attempting to acquire lock mutex_rankB/50 out of order with lock mutex_rankA/50 -- possible deadlock") {
|
||||
JavaThread* THREAD = JavaThread::current();
|
||||
ThreadInVMfromNative invm(THREAD);
|
||||
|
||||
Mutex* mutex_rankA = new Mutex(rankA, "mutex_rankA", false, Mutex::_safepoint_check_always);
|
||||
Mutex* mutex_rankB = new Mutex(rankA, "mutex_rankB", false, Mutex::_safepoint_check_always);
|
||||
|
||||
mutex_rankA->lock();
|
||||
mutex_rankB->lock();
|
||||
mutex_rankB->unlock();
|
||||
mutex_rankA->unlock();
|
||||
}
|
||||
|
||||
TEST_OTHER_VM(MutexRank, mutex_trylock_rank_out_of_orderA) {
|
||||
JavaThread* THREAD = JavaThread::current();
|
||||
ThreadInVMfromNative invm(THREAD);
|
||||
|
||||
Mutex* mutex_rankA = new Mutex(rankA, "mutex_rankA", false, Mutex::_safepoint_check_always);
|
||||
Mutex* mutex_rankA_plus_one = new Mutex(rankA + 1, "mutex_rankA_plus_one", false, Mutex::_safepoint_check_always);
|
||||
Mutex* mutex_rankA_plus_two = new Mutex(rankA + 2, "mutex_rankA_plus_two", false, Mutex::_safepoint_check_always);
|
||||
|
||||
mutex_rankA_plus_one->lock();
|
||||
mutex_rankA_plus_two->try_lock_without_rank_check();
|
||||
mutex_rankA->lock();
|
||||
mutex_rankA->unlock();
|
||||
mutex_rankA_plus_two->unlock();
|
||||
mutex_rankA_plus_one->unlock();
|
||||
}
|
||||
|
||||
TEST_VM_ASSERT_MSG(MutexRank, mutex_trylock_rank_out_of_orderB,
|
||||
"Attempting to acquire lock mutex_rankA_plus_one/51 out of order with lock mutex_rankA/50 -- possible deadlock") {
|
||||
JavaThread* THREAD = JavaThread::current();
|
||||
ThreadInVMfromNative invm(THREAD);
|
||||
|
||||
Mutex* mutex_rankA = new Mutex(rankA, "mutex_rankA", false, Mutex::_safepoint_check_always);
|
||||
Mutex* mutex_rankA_plus_one = new Mutex(rankA + 1, "mutex_rankA_plus_one", false, Mutex::_safepoint_check_always);
|
||||
|
||||
mutex_rankA->lock();
|
||||
mutex_rankA_plus_one->try_lock_without_rank_check();
|
||||
mutex_rankA_plus_one->unlock();
|
||||
mutex_rankA_plus_one->try_lock();
|
||||
mutex_rankA_plus_one->unlock();
|
||||
mutex_rankA->unlock();
|
||||
}
|
||||
|
||||
TEST_OTHER_VM(MutexRank, monitor_wait_rank_in_order) {
|
||||
JavaThread* THREAD = JavaThread::current();
|
||||
ThreadInVMfromNative invm(THREAD);
|
||||
|
||||
Monitor* monitor_rankA = new Monitor(rankA, "monitor_rankA", false, Mutex::_safepoint_check_always);
|
||||
Monitor* monitor_rankA_plus_one = new Monitor(rankA + 1, "monitor_rankA_plus_one", false, Mutex::_safepoint_check_always);
|
||||
|
||||
monitor_rankA_plus_one->lock();
|
||||
monitor_rankA->lock();
|
||||
monitor_rankA->wait(1);
|
||||
monitor_rankA->unlock();
|
||||
monitor_rankA_plus_one->unlock();
|
||||
}
|
||||
|
||||
TEST_VM_ASSERT_MSG(MutexRank, monitor_wait_rank_out_of_order,
|
||||
"Attempting to wait on monitor monitor_rankA_plus_one/51 while holding lock monitor_rankA/50 "
|
||||
"-- possible deadlock. Should wait on the least ranked monitor from all owned locks.") {
|
||||
JavaThread* THREAD = JavaThread::current();
|
||||
ThreadInVMfromNative invm(THREAD);
|
||||
|
||||
Monitor* monitor_rankA = new Monitor(rankA, "monitor_rankA", false, Mutex::_safepoint_check_always);
|
||||
Monitor* monitor_rankA_plus_one = new Monitor(rankA + 1, "monitor_rankA_plus_one", false, Mutex::_safepoint_check_always);
|
||||
|
||||
monitor_rankA_plus_one->lock();
|
||||
monitor_rankA->lock();
|
||||
monitor_rankA_plus_one->wait(1);
|
||||
monitor_rankA_plus_one->unlock();
|
||||
monitor_rankA->unlock();
|
||||
}
|
||||
|
||||
TEST_VM_ASSERT_MSG(MutexRank, monitor_wait_rank_out_of_order_trylock,
|
||||
"Attempting to wait on monitor monitor_rankA_plus_one/51 while holding lock monitor_rankA/50 "
|
||||
"-- possible deadlock. Should wait on the least ranked monitor from all owned locks.") {
|
||||
JavaThread* THREAD = JavaThread::current();
|
||||
ThreadInVMfromNative invm(THREAD);
|
||||
|
||||
Monitor* monitor_rankA = new Monitor(rankA, "monitor_rankA", false, Mutex::_safepoint_check_always);
|
||||
Monitor* monitor_rankA_plus_one = new Monitor(rankA + 1, "monitor_rankA_plus_one", false, Mutex::_safepoint_check_always);
|
||||
|
||||
monitor_rankA->lock();
|
||||
monitor_rankA_plus_one->try_lock_without_rank_check();
|
||||
monitor_rankA_plus_one->wait();
|
||||
monitor_rankA_plus_one->unlock();
|
||||
monitor_rankA->unlock();
|
||||
}
|
||||
|
||||
TEST_VM_ASSERT_MSG(MutexRank, monitor_wait_rank_special,
|
||||
"Attempting to wait on monitor monitor_rank_special_minus_one/5 while holding lock monitor_rank_special/6 "
|
||||
"-- possible deadlock. Should not block\\(wait\\) while holding a lock of rank special.") {
|
||||
JavaThread* THREAD = JavaThread::current();
|
||||
ThreadInVMfromNative invm(THREAD);
|
||||
|
||||
Monitor* monitor_rank_special = new Monitor(Mutex::special, "monitor_rank_special", false, Mutex::_safepoint_check_never);
|
||||
Monitor* monitor_rank_special_minus_one = new Monitor(Mutex::special - 1, "monitor_rank_special_minus_one", false, Mutex::_safepoint_check_never);
|
||||
|
||||
monitor_rank_special->lock_without_safepoint_check();
|
||||
monitor_rank_special_minus_one->lock_without_safepoint_check();
|
||||
monitor_rank_special_minus_one->wait_without_safepoint_check(1);
|
||||
monitor_rank_special_minus_one->unlock();
|
||||
monitor_rank_special->unlock();
|
||||
}
|
||||
#endif // ASSERT
|
Loading…
x
Reference in New Issue
Block a user