mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8230003: Make Monitor inherit from Mutex
Reverse inheritance that makes more sense. Reviewed-by: dholmes, rehn, pchilanomate
This commit is contained in:
parent
a405118f90
commit
da18495f38
10 changed files with 143 additions and 169 deletions
|
@ -2674,8 +2674,8 @@ void CompileBroker::print_heapinfo(outputStream* out, const char* function, size
|
||||||
// for the entire duration of aggregation and printing. That makes sure
|
// for the entire duration of aggregation and printing. That makes sure
|
||||||
// we see a consistent picture and do not run into issues caused by
|
// we see a consistent picture and do not run into issues caused by
|
||||||
// the CodeHeap being altered concurrently.
|
// the CodeHeap being altered concurrently.
|
||||||
Monitor* global_lock = allFun ? CodeCache_lock : NULL;
|
Mutex* global_lock = allFun ? CodeCache_lock : NULL;
|
||||||
Monitor* function_lock = allFun ? NULL : CodeCache_lock;
|
Mutex* function_lock = allFun ? NULL : CodeCache_lock;
|
||||||
ts_global.update(); // record starting point
|
ts_global.update(); // record starting point
|
||||||
MutexLocker mu2(global_lock, Mutex::_no_safepoint_check_flag);
|
MutexLocker mu2(global_lock, Mutex::_no_safepoint_check_flag);
|
||||||
if (global_lock != NULL) {
|
if (global_lock != NULL) {
|
||||||
|
|
|
@ -356,9 +356,9 @@ static void prepare_for_emergency_dump(Thread* thread) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
Monitor* owned_lock = thread->owned_locks();
|
Mutex* owned_lock = thread->owned_locks();
|
||||||
while (owned_lock != NULL) {
|
while (owned_lock != NULL) {
|
||||||
Monitor* next = owned_lock->next();
|
Mutex* next = owned_lock->next();
|
||||||
owned_lock->unlock();
|
owned_lock->unlock();
|
||||||
owned_lock = next;
|
owned_lock = next;
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,7 +171,7 @@
|
||||||
LOG_TAG(mirror) \
|
LOG_TAG(mirror) \
|
||||||
LOG_TAG(verification) \
|
LOG_TAG(verification) \
|
||||||
LOG_TAG(verify) \
|
LOG_TAG(verify) \
|
||||||
LOG_TAG(vmmonitor) \
|
LOG_TAG(vmmutex) \
|
||||||
LOG_TAG(vmoperation) \
|
LOG_TAG(vmoperation) \
|
||||||
LOG_TAG(vmthread) \
|
LOG_TAG(vmthread) \
|
||||||
LOG_TAG(vtables) \
|
LOG_TAG(vtables) \
|
||||||
|
|
|
@ -254,30 +254,30 @@ class ThreadBlockInVM : public ThreadStateTransition {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Unlike ThreadBlockInVM, this class is designed to avoid certain deadlock scenarios while making
|
// Unlike ThreadBlockInVM, this class is designed to avoid certain deadlock scenarios while making
|
||||||
// transitions inside class Monitor in cases where we need to block for a safepoint or handshake. It
|
// transitions inside class Mutex in cases where we need to block for a safepoint or handshake. It
|
||||||
// receives an extra argument compared to ThreadBlockInVM, the address of a pointer to the monitor we
|
// receives an extra argument compared to ThreadBlockInVM, the address of a pointer to the mutex we
|
||||||
// are trying to acquire. This will be used to access and release the monitor if needed to avoid
|
// are trying to acquire. This will be used to access and release the mutex if needed to avoid
|
||||||
// said deadlocks.
|
// said deadlocks.
|
||||||
// It works like ThreadBlockInVM but differs from it in two ways:
|
// It works like ThreadBlockInVM but differs from it in two ways:
|
||||||
// - When transitioning in (constructor), it checks for safepoints without blocking, i.e., calls
|
// - When transitioning in (constructor), it checks for safepoints without blocking, i.e., calls
|
||||||
// back if needed to allow a pending safepoint to continue but does not block in it.
|
// back if needed to allow a pending safepoint to continue but does not block in it.
|
||||||
// - When transitioning back (destructor), if there is a pending safepoint or handshake it releases
|
// - When transitioning back (destructor), if there is a pending safepoint or handshake it releases
|
||||||
// the monitor that is only partially acquired.
|
// the mutex that is only partially acquired.
|
||||||
class ThreadBlockInVMWithDeadlockCheck : public ThreadStateTransition {
|
class ThreadBlockInVMWithDeadlockCheck : public ThreadStateTransition {
|
||||||
private:
|
private:
|
||||||
Monitor** _in_flight_monitor_adr;
|
Mutex** _in_flight_mutex_addr;
|
||||||
|
|
||||||
void release_monitor() {
|
void release_mutex() {
|
||||||
assert(_in_flight_monitor_adr != NULL, "_in_flight_monitor_adr should have been set on constructor");
|
assert(_in_flight_mutex_addr != NULL, "_in_flight_mutex_addr should have been set on constructor");
|
||||||
Monitor* in_flight_monitor = *_in_flight_monitor_adr;
|
Mutex* in_flight_mutex = *_in_flight_mutex_addr;
|
||||||
if (in_flight_monitor != NULL) {
|
if (in_flight_mutex != NULL) {
|
||||||
in_flight_monitor->release_for_safepoint();
|
in_flight_mutex->release_for_safepoint();
|
||||||
*_in_flight_monitor_adr = NULL;
|
*_in_flight_mutex_addr = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
ThreadBlockInVMWithDeadlockCheck(JavaThread* thread, Monitor** in_flight_monitor_adr)
|
ThreadBlockInVMWithDeadlockCheck(JavaThread* thread, Mutex** in_flight_mutex_addr)
|
||||||
: ThreadStateTransition(thread), _in_flight_monitor_adr(in_flight_monitor_adr) {
|
: ThreadStateTransition(thread), _in_flight_mutex_addr(in_flight_mutex_addr) {
|
||||||
// Once we are blocked vm expects stack to be walkable
|
// Once we are blocked vm expects stack to be walkable
|
||||||
thread->frame_anchor()->make_walkable(thread);
|
thread->frame_anchor()->make_walkable(thread);
|
||||||
|
|
||||||
|
@ -293,7 +293,7 @@ class ThreadBlockInVMWithDeadlockCheck : public ThreadStateTransition {
|
||||||
_thread->set_thread_state_fence((JavaThreadState)(_thread_blocked_trans));
|
_thread->set_thread_state_fence((JavaThreadState)(_thread_blocked_trans));
|
||||||
|
|
||||||
if (SafepointMechanism::should_block(_thread)) {
|
if (SafepointMechanism::should_block(_thread)) {
|
||||||
release_monitor();
|
release_mutex();
|
||||||
SafepointMechanism::block_if_requested(_thread);
|
SafepointMechanism::block_if_requested(_thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,27 +33,27 @@
|
||||||
#include "utilities/macros.hpp"
|
#include "utilities/macros.hpp"
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
void Monitor::check_safepoint_state(Thread* thread, bool do_safepoint_check) {
|
void Mutex::check_safepoint_state(Thread* thread, bool do_safepoint_check) {
|
||||||
// If the JavaThread checks for safepoint, verify that the lock wasn't created with safepoint_check_never.
|
// If the JavaThread checks for safepoint, verify that the lock wasn't created with safepoint_check_never.
|
||||||
SafepointCheckRequired not_allowed = do_safepoint_check ? Monitor::_safepoint_check_never :
|
SafepointCheckRequired not_allowed = do_safepoint_check ? Mutex::_safepoint_check_never :
|
||||||
Monitor::_safepoint_check_always;
|
Mutex::_safepoint_check_always;
|
||||||
assert(!thread->is_active_Java_thread() || _safepoint_check_required != not_allowed,
|
assert(!thread->is_active_Java_thread() || _safepoint_check_required != not_allowed,
|
||||||
"This lock should %s have a safepoint check for Java threads: %s",
|
"This lock should %s have a safepoint check for Java threads: %s",
|
||||||
_safepoint_check_required ? "always" : "never", name());
|
_safepoint_check_required ? "always" : "never", name());
|
||||||
|
|
||||||
// If defined with safepoint_check_never, a NonJavaThread should never ask to safepoint check either.
|
// If defined with safepoint_check_never, a NonJavaThread should never ask to safepoint check either.
|
||||||
assert(thread->is_Java_thread() || !do_safepoint_check || _safepoint_check_required != Monitor::_safepoint_check_never,
|
assert(thread->is_Java_thread() || !do_safepoint_check || _safepoint_check_required != Mutex::_safepoint_check_never,
|
||||||
"NonJavaThread should not check for safepoint");
|
"NonJavaThread should not check for safepoint");
|
||||||
}
|
}
|
||||||
#endif // ASSERT
|
#endif // ASSERT
|
||||||
|
|
||||||
void Monitor::lock(Thread * self) {
|
void Mutex::lock(Thread * self) {
|
||||||
check_safepoint_state(self, true);
|
check_safepoint_state(self, true);
|
||||||
|
|
||||||
DEBUG_ONLY(check_prelock_state(self, true));
|
DEBUG_ONLY(check_prelock_state(self, true));
|
||||||
assert(_owner != self, "invariant");
|
assert(_owner != self, "invariant");
|
||||||
|
|
||||||
Monitor* in_flight_monitor = NULL;
|
Mutex* in_flight_mutex = NULL;
|
||||||
DEBUG_ONLY(int retry_cnt = 0;)
|
DEBUG_ONLY(int retry_cnt = 0;)
|
||||||
bool is_active_Java_thread = self->is_active_Java_thread();
|
bool is_active_Java_thread = self->is_active_Java_thread();
|
||||||
while (!_lock.try_lock()) {
|
while (!_lock.try_lock()) {
|
||||||
|
@ -62,18 +62,18 @@ void Monitor::lock(Thread * self) {
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
check_block_state(self);
|
check_block_state(self);
|
||||||
if (retry_cnt++ > 3) {
|
if (retry_cnt++ > 3) {
|
||||||
log_trace(vmmonitor)("JavaThread " INTPTR_FORMAT " on %d attempt trying to acquire vmmonitor %s", p2i(self), retry_cnt, _name);
|
log_trace(vmmutex)("JavaThread " INTPTR_FORMAT " on %d attempt trying to acquire vmmutex %s", p2i(self), retry_cnt, _name);
|
||||||
}
|
}
|
||||||
#endif // ASSERT
|
#endif // ASSERT
|
||||||
|
|
||||||
// Is it a JavaThread participating in the safepoint protocol.
|
// Is it a JavaThread participating in the safepoint protocol.
|
||||||
if (is_active_Java_thread) {
|
if (is_active_Java_thread) {
|
||||||
assert(rank() > Mutex::special, "Potential deadlock with special or lesser rank mutex");
|
assert(rank() > Mutex::special, "Potential deadlock with special or lesser rank mutex");
|
||||||
{ ThreadBlockInVMWithDeadlockCheck tbivmdc((JavaThread *) self, &in_flight_monitor);
|
{ ThreadBlockInVMWithDeadlockCheck tbivmdc((JavaThread *) self, &in_flight_mutex);
|
||||||
in_flight_monitor = this; // save for ~ThreadBlockInVMWithDeadlockCheck
|
in_flight_mutex = this; // save for ~ThreadBlockInVMWithDeadlockCheck
|
||||||
_lock.lock();
|
_lock.lock();
|
||||||
}
|
}
|
||||||
if (in_flight_monitor != NULL) {
|
if (in_flight_mutex != NULL) {
|
||||||
// Not unlocked by ~ThreadBlockInVMWithDeadlockCheck
|
// Not unlocked by ~ThreadBlockInVMWithDeadlockCheck
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@ void Monitor::lock(Thread * self) {
|
||||||
set_owner(self);
|
set_owner(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Monitor::lock() {
|
void Mutex::lock() {
|
||||||
this->lock(Thread::current());
|
this->lock(Thread::current());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ void Monitor::lock() {
|
||||||
// safepoint-safe and so will prevent a safepoint from being reached. If used
|
// safepoint-safe and so will prevent a safepoint from being reached. If used
|
||||||
// in the wrong way this can lead to a deadlock with the safepoint code.
|
// in the wrong way this can lead to a deadlock with the safepoint code.
|
||||||
|
|
||||||
void Monitor::lock_without_safepoint_check(Thread * self) {
|
void Mutex::lock_without_safepoint_check(Thread * self) {
|
||||||
check_safepoint_state(self, false);
|
check_safepoint_state(self, false);
|
||||||
assert(_owner != self, "invariant");
|
assert(_owner != self, "invariant");
|
||||||
_lock.lock();
|
_lock.lock();
|
||||||
|
@ -105,14 +105,14 @@ void Monitor::lock_without_safepoint_check(Thread * self) {
|
||||||
set_owner(self);
|
set_owner(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Monitor::lock_without_safepoint_check() {
|
void Mutex::lock_without_safepoint_check() {
|
||||||
lock_without_safepoint_check(Thread::current());
|
lock_without_safepoint_check(Thread::current());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Returns true if thread succeeds in grabbing the lock, otherwise false.
|
// Returns true if thread succeeds in grabbing the lock, otherwise false.
|
||||||
|
|
||||||
bool Monitor::try_lock() {
|
bool Mutex::try_lock() {
|
||||||
Thread * const self = Thread::current();
|
Thread * const self = Thread::current();
|
||||||
DEBUG_ONLY(check_prelock_state(self, false);)
|
DEBUG_ONLY(check_prelock_state(self, false);)
|
||||||
|
|
||||||
|
@ -124,12 +124,12 @@ bool Monitor::try_lock() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Monitor::release_for_safepoint() {
|
void Mutex::release_for_safepoint() {
|
||||||
assert_owner(NULL);
|
assert_owner(NULL);
|
||||||
_lock.unlock();
|
_lock.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Monitor::unlock() {
|
void Mutex::unlock() {
|
||||||
assert_owner(Thread::current());
|
assert_owner(Thread::current());
|
||||||
set_owner(NULL);
|
set_owner(NULL);
|
||||||
_lock.unlock();
|
_lock.unlock();
|
||||||
|
@ -147,7 +147,7 @@ void Monitor::notify_all() {
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
void Monitor::assert_wait_lock_state(Thread* self) {
|
void Monitor::assert_wait_lock_state(Thread* self) {
|
||||||
Monitor* least = get_least_ranked_lock_besides_this(self->owned_locks());
|
Mutex* least = get_least_ranked_lock_besides_this(self->owned_locks());
|
||||||
assert(least != this, "Specification of get_least_... call above");
|
assert(least != this, "Specification of get_least_... call above");
|
||||||
if (least != NULL && least->rank() <= special) {
|
if (least != NULL && least->rank() <= special) {
|
||||||
::tty->print("Attempting to wait on monitor %s/%d while holding"
|
::tty->print("Attempting to wait on monitor %s/%d while holding"
|
||||||
|
@ -194,10 +194,10 @@ bool Monitor::wait(long timeout, bool as_suspend_equivalent) {
|
||||||
// abdicating the lock in wait
|
// abdicating the lock in wait
|
||||||
set_owner(NULL);
|
set_owner(NULL);
|
||||||
JavaThread *jt = (JavaThread *)self;
|
JavaThread *jt = (JavaThread *)self;
|
||||||
Monitor* in_flight_monitor = NULL;
|
Mutex* in_flight_mutex = NULL;
|
||||||
|
|
||||||
{
|
{
|
||||||
ThreadBlockInVMWithDeadlockCheck tbivmdc(jt, &in_flight_monitor);
|
ThreadBlockInVMWithDeadlockCheck tbivmdc(jt, &in_flight_mutex);
|
||||||
OSThreadWaitState osts(self->osthread(), false /* not Object.wait() */);
|
OSThreadWaitState osts(self->osthread(), false /* not Object.wait() */);
|
||||||
if (as_suspend_equivalent) {
|
if (as_suspend_equivalent) {
|
||||||
jt->set_suspend_equivalent();
|
jt->set_suspend_equivalent();
|
||||||
|
@ -206,7 +206,7 @@ bool Monitor::wait(long timeout, bool as_suspend_equivalent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
wait_status = _lock.wait(timeout);
|
wait_status = _lock.wait(timeout);
|
||||||
in_flight_monitor = this; // save for ~ThreadBlockInVMWithDeadlockCheck
|
in_flight_mutex = this; // save for ~ThreadBlockInVMWithDeadlockCheck
|
||||||
|
|
||||||
// were we externally suspended while we were waiting?
|
// were we externally suspended while we were waiting?
|
||||||
if (as_suspend_equivalent && jt->handle_special_suspend_equivalent_condition()) {
|
if (as_suspend_equivalent && jt->handle_special_suspend_equivalent_condition()) {
|
||||||
|
@ -220,7 +220,7 @@ bool Monitor::wait(long timeout, bool as_suspend_equivalent) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_flight_monitor != NULL) {
|
if (in_flight_mutex != NULL) {
|
||||||
// Not unlocked by ~ThreadBlockInVMWithDeadlockCheck
|
// Not unlocked by ~ThreadBlockInVMWithDeadlockCheck
|
||||||
assert_owner(NULL);
|
assert_owner(NULL);
|
||||||
// Conceptually reestablish ownership of the lock.
|
// Conceptually reestablish ownership of the lock.
|
||||||
|
@ -232,7 +232,7 @@ bool Monitor::wait(long timeout, bool as_suspend_equivalent) {
|
||||||
return wait_status != 0; // return true IFF timeout
|
return wait_status != 0; // return true IFF timeout
|
||||||
}
|
}
|
||||||
|
|
||||||
Monitor::~Monitor() {
|
Mutex::~Mutex() {
|
||||||
assert_owner(NULL);
|
assert_owner(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,34 +241,34 @@ bool is_sometimes_ok(const char* name) {
|
||||||
return (strcmp(name, "Threads_lock") == 0 || strcmp(name, "Heap_lock") == 0 || strcmp(name, "SR_lock") == 0);
|
return (strcmp(name, "Threads_lock") == 0 || strcmp(name, "Heap_lock") == 0 || strcmp(name, "SR_lock") == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Monitor::Monitor(int Rank, const char * name, bool allow_vm_block,
|
Mutex::Mutex(int Rank, const char * name, bool allow_vm_block,
|
||||||
SafepointCheckRequired safepoint_check_required) : _owner(NULL) {
|
SafepointCheckRequired safepoint_check_required) : _owner(NULL) {
|
||||||
assert(os::mutex_init_done(), "Too early!");
|
assert(os::mutex_init_done(), "Too early!");
|
||||||
if (name == NULL) {
|
if (name == NULL) {
|
||||||
strcpy(_name, "UNKNOWN");
|
strcpy(_name, "UNKNOWN");
|
||||||
} else {
|
} else {
|
||||||
strncpy(_name, name, MONITOR_NAME_LEN - 1);
|
strncpy(_name, name, MUTEX_NAME_LEN - 1);
|
||||||
_name[MONITOR_NAME_LEN - 1] = '\0';
|
_name[MUTEX_NAME_LEN - 1] = '\0';
|
||||||
}
|
}
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
_allow_vm_block = allow_vm_block;
|
_allow_vm_block = allow_vm_block;
|
||||||
_rank = Rank;
|
_rank = Rank;
|
||||||
_safepoint_check_required = safepoint_check_required;
|
_safepoint_check_required = safepoint_check_required;
|
||||||
|
|
||||||
assert(_safepoint_check_required != Monitor::_safepoint_check_sometimes || is_sometimes_ok(name),
|
assert(_safepoint_check_required != Mutex::_safepoint_check_sometimes || is_sometimes_ok(name),
|
||||||
"Lock has _safepoint_check_sometimes %s", name);
|
"Lock has _safepoint_check_sometimes %s", name);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
Mutex::Mutex(int Rank, const char * name, bool allow_vm_block,
|
Monitor::Monitor(int Rank, const char * name, bool allow_vm_block,
|
||||||
SafepointCheckRequired safepoint_check_required) :
|
SafepointCheckRequired safepoint_check_required) :
|
||||||
Monitor(Rank, name, allow_vm_block, safepoint_check_required) {}
|
Mutex(Rank, name, allow_vm_block, safepoint_check_required) {}
|
||||||
|
|
||||||
bool Monitor::owned_by_self() const {
|
bool Mutex::owned_by_self() const {
|
||||||
return _owner == Thread::current();
|
return _owner == Thread::current();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Monitor::print_on_error(outputStream* st) const {
|
void Mutex::print_on_error(outputStream* st) const {
|
||||||
st->print("[" PTR_FORMAT, p2i(this));
|
st->print("[" PTR_FORMAT, p2i(this));
|
||||||
st->print("] %s", _name);
|
st->print("] %s", _name);
|
||||||
st->print(" - owner thread: " PTR_FORMAT, p2i(_owner));
|
st->print(" - owner thread: " PTR_FORMAT, p2i(_owner));
|
||||||
|
@ -278,7 +278,7 @@ void Monitor::print_on_error(outputStream* st) const {
|
||||||
// Non-product code
|
// Non-product code
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
void Monitor::print_on(outputStream* st) const {
|
void Mutex::print_on(outputStream* st) const {
|
||||||
st->print_cr("Mutex: [" PTR_FORMAT "] %s - owner: " PTR_FORMAT,
|
st->print_cr("Mutex: [" PTR_FORMAT "] %s - owner: " PTR_FORMAT,
|
||||||
p2i(this), _name, p2i(_owner));
|
p2i(this), _name, p2i(_owner));
|
||||||
}
|
}
|
||||||
|
@ -287,7 +287,7 @@ void Monitor::print_on(outputStream* st) const {
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
|
|
||||||
void Monitor::assert_owner(Thread * expected) {
|
void Mutex::assert_owner(Thread * expected) {
|
||||||
const char* msg = "invalid owner";
|
const char* msg = "invalid owner";
|
||||||
if (expected == NULL) {
|
if (expected == NULL) {
|
||||||
msg = "should be un-owned";
|
msg = "should be un-owned";
|
||||||
|
@ -300,8 +300,8 @@ void Monitor::assert_owner(Thread * expected) {
|
||||||
msg, p2i(_owner), p2i(expected));
|
msg, p2i(_owner), p2i(expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
Monitor * Monitor::get_least_ranked_lock(Monitor * locks) {
|
Mutex* Mutex::get_least_ranked_lock(Mutex* locks) {
|
||||||
Monitor *res, *tmp;
|
Mutex *res, *tmp;
|
||||||
for (res = tmp = locks; tmp != NULL; tmp = tmp->next()) {
|
for (res = tmp = locks; tmp != NULL; tmp = tmp->next()) {
|
||||||
if (tmp->rank() < res->rank()) {
|
if (tmp->rank() < res->rank()) {
|
||||||
res = tmp;
|
res = tmp;
|
||||||
|
@ -320,8 +320,8 @@ Monitor * Monitor::get_least_ranked_lock(Monitor * locks) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
Monitor* Monitor::get_least_ranked_lock_besides_this(Monitor* locks) {
|
Mutex* Mutex::get_least_ranked_lock_besides_this(Mutex* locks) {
|
||||||
Monitor *res, *tmp;
|
Mutex *res, *tmp;
|
||||||
for (res = NULL, tmp = locks; tmp != NULL; tmp = tmp->next()) {
|
for (res = NULL, tmp = locks; tmp != NULL; tmp = tmp->next()) {
|
||||||
if (tmp != this && (res == NULL || tmp->rank() < res->rank())) {
|
if (tmp != this && (res == NULL || tmp->rank() < res->rank())) {
|
||||||
res = tmp;
|
res = tmp;
|
||||||
|
@ -341,7 +341,7 @@ Monitor* Monitor::get_least_ranked_lock_besides_this(Monitor* locks) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Monitor::contains(Monitor* locks, Monitor * lock) {
|
bool Mutex::contains(Mutex* locks, Mutex* lock) {
|
||||||
for (; locks != NULL; locks = locks->next()) {
|
for (; locks != NULL; locks = locks->next()) {
|
||||||
if (locks == lock) {
|
if (locks == lock) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -356,7 +356,7 @@ bool Monitor::contains(Monitor* locks, Monitor * lock) {
|
||||||
// might indicate exposure to deadlock.
|
// might indicate exposure to deadlock.
|
||||||
// Rather like an EventListener for _owner (:>).
|
// Rather like an EventListener for _owner (:>).
|
||||||
|
|
||||||
void Monitor::set_owner_implementation(Thread *new_owner) {
|
void Mutex::set_owner_implementation(Thread *new_owner) {
|
||||||
// This function is solely responsible for maintaining
|
// This function is solely responsible for maintaining
|
||||||
// and checking the invariant that threads and locks
|
// and checking the invariant that threads and locks
|
||||||
// are in a 1/N relation, with some some locks unowned.
|
// are in a 1/N relation, with some some locks unowned.
|
||||||
|
@ -377,7 +377,7 @@ void Monitor::set_owner_implementation(Thread *new_owner) {
|
||||||
// link "this" into the owned locks list
|
// link "this" into the owned locks list
|
||||||
|
|
||||||
#ifdef ASSERT // Thread::_owned_locks is under the same ifdef
|
#ifdef ASSERT // Thread::_owned_locks is under the same ifdef
|
||||||
Monitor* locks = get_least_ranked_lock(new_owner->owned_locks());
|
Mutex* locks = get_least_ranked_lock(new_owner->owned_locks());
|
||||||
// Mutex::set_owner_implementation is a friend of Thread
|
// Mutex::set_owner_implementation is a friend of Thread
|
||||||
|
|
||||||
assert(this->rank() >= 0, "bad lock rank");
|
assert(this->rank() >= 0, "bad lock rank");
|
||||||
|
@ -415,11 +415,11 @@ void Monitor::set_owner_implementation(Thread *new_owner) {
|
||||||
_owner = NULL; // set the owner
|
_owner = NULL; // set the owner
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
Monitor *locks = old_owner->owned_locks();
|
Mutex* locks = old_owner->owned_locks();
|
||||||
|
|
||||||
// remove "this" from the owned locks list
|
// remove "this" from the owned locks list
|
||||||
|
|
||||||
Monitor *prev = NULL;
|
Mutex* prev = NULL;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (; locks != NULL; prev = locks, locks = locks->next()) {
|
for (; locks != NULL; prev = locks, locks = locks->next()) {
|
||||||
if (locks == this) {
|
if (locks == this) {
|
||||||
|
@ -440,7 +440,7 @@ void Monitor::set_owner_implementation(Thread *new_owner) {
|
||||||
|
|
||||||
|
|
||||||
// Factored out common sanity checks for locking mutex'es. Used by lock() and try_lock()
|
// Factored out common sanity checks for locking mutex'es. Used by lock() and try_lock()
|
||||||
void Monitor::check_prelock_state(Thread *thread, bool safepoint_check) {
|
void Mutex::check_prelock_state(Thread *thread, bool safepoint_check) {
|
||||||
if (safepoint_check) {
|
if (safepoint_check) {
|
||||||
assert((!thread->is_active_Java_thread() || ((JavaThread *)thread)->thread_state() == _thread_in_vm)
|
assert((!thread->is_active_Java_thread() || ((JavaThread *)thread)->thread_state() == _thread_in_vm)
|
||||||
|| rank() == Mutex::special, "wrong thread state for using locks");
|
|| rank() == Mutex::special, "wrong thread state for using locks");
|
||||||
|
@ -454,13 +454,13 @@ void Monitor::check_prelock_state(Thread *thread, bool safepoint_check) {
|
||||||
"locking not allowed when crash protection is set");
|
"locking not allowed when crash protection is set");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Monitor::check_block_state(Thread *thread) {
|
void Mutex::check_block_state(Thread *thread) {
|
||||||
if (!_allow_vm_block && thread->is_VM_thread()) {
|
if (!_allow_vm_block && thread->is_VM_thread()) {
|
||||||
warning("VM thread blocked on lock");
|
warning("VM thread blocked on lock");
|
||||||
print();
|
print();
|
||||||
BREAKPOINT;
|
BREAKPOINT;
|
||||||
}
|
}
|
||||||
assert(_owner != thread, "deadlock: blocking on monitor owned by current thread");
|
assert(_owner != thread, "deadlock: blocking on mutex owned by current thread");
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // PRODUCT
|
#endif // PRODUCT
|
||||||
|
|
|
@ -32,12 +32,12 @@
|
||||||
// variable that supports lock ownership tracking, lock ranking for deadlock
|
// variable that supports lock ownership tracking, lock ranking for deadlock
|
||||||
// detection and coordinates with the safepoint protocol.
|
// detection and coordinates with the safepoint protocol.
|
||||||
|
|
||||||
// The default length of monitor name was originally chosen to be 64 to avoid
|
// The default length of mutex name was originally chosen to be 64 to avoid
|
||||||
// false sharing. Now, PaddedMonitor is available for this purpose.
|
// false sharing. Now, PaddedMutex and PaddedMonitor are available for this purpose.
|
||||||
// TODO: Check if _name[MONITOR_NAME_LEN] should better get replaced by const char*.
|
// TODO: Check if _name[MUTEX_NAME_LEN] should better get replaced by const char*.
|
||||||
static const int MONITOR_NAME_LEN = 64;
|
static const int MUTEX_NAME_LEN = 64;
|
||||||
|
|
||||||
class Monitor : public CHeapObj<mtSynchronizer> {
|
class Mutex : public CHeapObj<mtSynchronizer> {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// A special lock: Is a lock where you are guaranteed not to block while you are
|
// A special lock: Is a lock where you are guaranteed not to block while you are
|
||||||
|
@ -78,17 +78,17 @@ class Monitor : public CHeapObj<mtSynchronizer> {
|
||||||
protected: // Monitor-Mutex metadata
|
protected: // Monitor-Mutex metadata
|
||||||
Thread * volatile _owner; // The owner of the lock
|
Thread * volatile _owner; // The owner of the lock
|
||||||
os::PlatformMonitor _lock; // Native monitor implementation
|
os::PlatformMonitor _lock; // Native monitor implementation
|
||||||
char _name[MONITOR_NAME_LEN]; // Name of mutex/monitor
|
char _name[MUTEX_NAME_LEN]; // Name of mutex/monitor
|
||||||
|
|
||||||
// Debugging fields for naming, deadlock detection, etc. (some only used in debug mode)
|
// Debugging fields for naming, deadlock detection, etc. (some only used in debug mode)
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
bool _allow_vm_block;
|
bool _allow_vm_block;
|
||||||
DEBUG_ONLY(int _rank;) // rank (to avoid/detect potential deadlocks)
|
DEBUG_ONLY(int _rank;) // rank (to avoid/detect potential deadlocks)
|
||||||
DEBUG_ONLY(Monitor * _next;) // Used by a Thread to link up owned locks
|
DEBUG_ONLY(Mutex* _next;) // Used by a Thread to link up owned locks
|
||||||
DEBUG_ONLY(Thread* _last_owner;) // the last thread to own the lock
|
DEBUG_ONLY(Thread* _last_owner;) // the last thread to own the lock
|
||||||
DEBUG_ONLY(static bool contains(Monitor * locks, Monitor * lock);)
|
DEBUG_ONLY(static bool contains(Mutex* locks, Mutex* lock);)
|
||||||
DEBUG_ONLY(static Monitor * get_least_ranked_lock(Monitor * locks);)
|
DEBUG_ONLY(static Mutex* get_least_ranked_lock(Mutex* locks);)
|
||||||
DEBUG_ONLY(Monitor * get_least_ranked_lock_besides_this(Monitor * locks);)
|
DEBUG_ONLY(Mutex* get_least_ranked_lock_besides_this(Mutex* locks);)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void set_owner_implementation(Thread* owner) PRODUCT_RETURN;
|
void set_owner_implementation(Thread* owner) PRODUCT_RETURN;
|
||||||
|
@ -96,7 +96,6 @@ class Monitor : public CHeapObj<mtSynchronizer> {
|
||||||
void check_block_state (Thread* thread) PRODUCT_RETURN;
|
void check_block_state (Thread* thread) PRODUCT_RETURN;
|
||||||
void check_safepoint_state (Thread* thread, bool safepoint_check) NOT_DEBUG_RETURN;
|
void check_safepoint_state (Thread* thread, bool safepoint_check) NOT_DEBUG_RETURN;
|
||||||
void assert_owner (Thread* expected) NOT_DEBUG_RETURN;
|
void assert_owner (Thread* expected) NOT_DEBUG_RETURN;
|
||||||
void assert_wait_lock_state (Thread* self) NOT_DEBUG_RETURN;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum {
|
enum {
|
||||||
|
@ -130,32 +129,21 @@ class Monitor : public CHeapObj<mtSynchronizer> {
|
||||||
};
|
};
|
||||||
|
|
||||||
enum SafepointCheckRequired {
|
enum SafepointCheckRequired {
|
||||||
_safepoint_check_never, // Monitors with this value will cause errors
|
_safepoint_check_never, // Mutexes with this value will cause errors
|
||||||
// when acquired by a JavaThread with a safepoint check.
|
// when acquired by a JavaThread with a safepoint check.
|
||||||
_safepoint_check_sometimes, // A couple of special locks are acquired by JavaThreads sometimes
|
_safepoint_check_sometimes, // A couple of special locks are acquired by JavaThreads sometimes
|
||||||
// with and sometimes without safepoint checks. These
|
// with and sometimes without safepoint checks. These
|
||||||
// locks will not produce errors when locked.
|
// locks will not produce errors when locked.
|
||||||
_safepoint_check_always // Monitors with this value will cause errors
|
_safepoint_check_always // Mutexes with this value will cause errors
|
||||||
// when acquired by a JavaThread without a safepoint check.
|
// when acquired by a JavaThread without a safepoint check.
|
||||||
};
|
};
|
||||||
|
|
||||||
NOT_PRODUCT(SafepointCheckRequired _safepoint_check_required;)
|
NOT_PRODUCT(SafepointCheckRequired _safepoint_check_required;)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Monitor(int rank, const char *name, bool allow_vm_block = false,
|
Mutex(int rank, const char *name, bool allow_vm_block = false,
|
||||||
SafepointCheckRequired safepoint_check_required = _safepoint_check_always);
|
SafepointCheckRequired safepoint_check_required = _safepoint_check_always);
|
||||||
~Monitor();
|
~Mutex();
|
||||||
|
|
||||||
// Wait until monitor is notified (or times out).
|
|
||||||
// Defaults are to make safepoint checks, wait time is forever (i.e.,
|
|
||||||
// zero), and not a suspend-equivalent condition. Returns true if wait
|
|
||||||
// times out; otherwise returns false.
|
|
||||||
bool wait(long timeout = 0,
|
|
||||||
bool as_suspend_equivalent = !_as_suspend_equivalent_flag);
|
|
||||||
bool wait_without_safepoint_check(long timeout = 0);
|
|
||||||
void notify();
|
|
||||||
void notify_all();
|
|
||||||
|
|
||||||
|
|
||||||
void lock(); // prints out warning if VM thread blocks
|
void lock(); // prints out warning if VM thread blocks
|
||||||
void lock(Thread *thread); // overloaded with current thread
|
void lock(Thread *thread); // overloaded with current thread
|
||||||
|
@ -186,19 +174,49 @@ class Monitor : public CHeapObj<mtSynchronizer> {
|
||||||
DEBUG_ONLY(int rank() const { return _rank; })
|
DEBUG_ONLY(int rank() const { return _rank; })
|
||||||
bool allow_vm_block() { return _allow_vm_block; }
|
bool allow_vm_block() { return _allow_vm_block; }
|
||||||
|
|
||||||
DEBUG_ONLY(Monitor *next() const { return _next; })
|
DEBUG_ONLY(Mutex *next() const { return _next; })
|
||||||
DEBUG_ONLY(void set_next(Monitor *next) { _next = next; })
|
DEBUG_ONLY(void set_next(Mutex *next) { _next = next; })
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void set_owner(Thread* owner) {
|
void set_owner(Thread* owner) {
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
set_owner_implementation(owner);
|
set_owner_implementation(owner);
|
||||||
DEBUG_ONLY(void verify_Monitor(Thread* thr);)
|
DEBUG_ONLY(void verify_mutex(Thread* thr);)
|
||||||
#else
|
#else
|
||||||
_owner = owner;
|
_owner = owner;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
// default destructor
|
||||||
|
|
||||||
|
// Wait until monitor is notified (or times out).
|
||||||
|
// Defaults are to make safepoint checks, wait time is forever (i.e.,
|
||||||
|
// zero), and not a suspend-equivalent condition. Returns true if wait
|
||||||
|
// times out; otherwise returns false.
|
||||||
|
bool wait(long timeout = 0,
|
||||||
|
bool as_suspend_equivalent = !_as_suspend_equivalent_flag);
|
||||||
|
bool wait_without_safepoint_check(long timeout = 0);
|
||||||
|
void notify();
|
||||||
|
void notify_all();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class PaddedMutex : public Mutex {
|
||||||
|
enum {
|
||||||
|
CACHE_LINE_PADDING = (int)DEFAULT_CACHE_LINE_SIZE - (int)sizeof(Mutex),
|
||||||
|
PADDING_LEN = CACHE_LINE_PADDING > 0 ? CACHE_LINE_PADDING : 1
|
||||||
|
};
|
||||||
|
char _padding[PADDING_LEN];
|
||||||
|
public:
|
||||||
|
PaddedMutex(int rank, const char *name, bool allow_vm_block = false,
|
||||||
|
SafepointCheckRequired safepoint_check_required = _safepoint_check_always) :
|
||||||
|
Mutex(rank, name, allow_vm_block, safepoint_check_required) {};
|
||||||
};
|
};
|
||||||
|
|
||||||
class PaddedMonitor : public Monitor {
|
class PaddedMonitor : public Monitor {
|
||||||
|
@ -213,49 +231,4 @@ class PaddedMonitor : public Monitor {
|
||||||
Monitor(rank, name, allow_vm_block, safepoint_check_required) {};
|
Monitor(rank, name, allow_vm_block, safepoint_check_required) {};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Normally we'd expect Monitor to extend Mutex in the sense that a monitor
|
|
||||||
// constructed from pthreads primitives might extend a mutex by adding
|
|
||||||
// a condvar and some extra metadata. In fact this was the case until J2SE7.
|
|
||||||
//
|
|
||||||
// Currently, however, the base object is a monitor. Monitor contains all the
|
|
||||||
// logic for wait(), notify(), etc. Mutex extends monitor and restricts the
|
|
||||||
// visibility of wait(), notify(), and notify_all().
|
|
||||||
//
|
|
||||||
// Another viable alternative would have been to have Monitor extend Mutex and
|
|
||||||
// implement all the normal mutex and wait()-notify() logic in Mutex base class.
|
|
||||||
// The wait()-notify() facility would be exposed via special protected member functions
|
|
||||||
// (e.g., _Wait() and _Notify()) in Mutex. Monitor would extend Mutex and expose wait()
|
|
||||||
// as a call to _Wait(). That is, the public wait() would be a wrapper for the protected
|
|
||||||
// _Wait().
|
|
||||||
//
|
|
||||||
// An even better alternative is to simply eliminate Mutex:: and use Monitor:: instead.
|
|
||||||
// After all, monitors are sufficient for Java-level synchronization. At one point in time
|
|
||||||
// there may have been some benefit to having distinct mutexes and monitors, but that time
|
|
||||||
// has passed.
|
|
||||||
//
|
|
||||||
|
|
||||||
class Mutex : public Monitor { // degenerate Monitor
|
|
||||||
public:
|
|
||||||
Mutex(int rank, const char *name, bool allow_vm_block = false,
|
|
||||||
SafepointCheckRequired safepoint_check_required = _safepoint_check_always);
|
|
||||||
// default destructor
|
|
||||||
private:
|
|
||||||
void notify();
|
|
||||||
void notify_all();
|
|
||||||
bool wait(long timeout, bool as_suspend_equivalent);
|
|
||||||
bool wait_without_safepoint_check(long timeout);
|
|
||||||
};
|
|
||||||
|
|
||||||
class PaddedMutex : public Mutex {
|
|
||||||
enum {
|
|
||||||
CACHE_LINE_PADDING = (int)DEFAULT_CACHE_LINE_SIZE - (int)sizeof(Mutex),
|
|
||||||
PADDING_LEN = CACHE_LINE_PADDING > 0 ? CACHE_LINE_PADDING : 1
|
|
||||||
};
|
|
||||||
char _padding[PADDING_LEN];
|
|
||||||
public:
|
|
||||||
PaddedMutex(int rank, const char *name, bool allow_vm_block = false,
|
|
||||||
SafepointCheckRequired safepoint_check_required = _safepoint_check_always) :
|
|
||||||
Mutex(rank, name, allow_vm_block, safepoint_check_required) {};
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // SHARE_RUNTIME_MUTEX_HPP
|
#endif // SHARE_RUNTIME_MUTEX_HPP
|
||||||
|
|
|
@ -130,7 +130,7 @@ Monitor* JfrThreadSampler_lock = NULL;
|
||||||
#ifndef SUPPORTS_NATIVE_CX8
|
#ifndef SUPPORTS_NATIVE_CX8
|
||||||
Mutex* UnsafeJlong_lock = NULL;
|
Mutex* UnsafeJlong_lock = NULL;
|
||||||
#endif
|
#endif
|
||||||
Monitor* CodeHeapStateAnalytics_lock = NULL;
|
Mutex* CodeHeapStateAnalytics_lock = NULL;
|
||||||
|
|
||||||
Mutex* MetaspaceExpand_lock = NULL;
|
Mutex* MetaspaceExpand_lock = NULL;
|
||||||
Mutex* ClassLoaderDataGraph_lock = NULL;
|
Mutex* ClassLoaderDataGraph_lock = NULL;
|
||||||
|
@ -153,11 +153,11 @@ Monitor* JVMCI_lock = NULL;
|
||||||
|
|
||||||
|
|
||||||
#define MAX_NUM_MUTEX 128
|
#define MAX_NUM_MUTEX 128
|
||||||
static Monitor * _mutex_array[MAX_NUM_MUTEX];
|
static Mutex* _mutex_array[MAX_NUM_MUTEX];
|
||||||
static int _num_mutex;
|
static int _num_mutex;
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
void assert_locked_or_safepoint(const Monitor * lock) {
|
void assert_locked_or_safepoint(const Mutex* lock) {
|
||||||
// check if this thread owns the lock (common case)
|
// check if this thread owns the lock (common case)
|
||||||
if (IgnoreLockingAssertions) return;
|
if (IgnoreLockingAssertions) return;
|
||||||
assert(lock != NULL, "Need non-NULL lock");
|
assert(lock != NULL, "Need non-NULL lock");
|
||||||
|
@ -171,7 +171,7 @@ void assert_locked_or_safepoint(const Monitor * lock) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// a weaker assertion than the above
|
// a weaker assertion than the above
|
||||||
void assert_locked_or_safepoint_weak(const Monitor * lock) {
|
void assert_locked_or_safepoint_weak(const Mutex* lock) {
|
||||||
if (IgnoreLockingAssertions) return;
|
if (IgnoreLockingAssertions) return;
|
||||||
assert(lock != NULL, "Need non-NULL lock");
|
assert(lock != NULL, "Need non-NULL lock");
|
||||||
if (lock->is_locked()) return;
|
if (lock->is_locked()) return;
|
||||||
|
@ -181,7 +181,7 @@ void assert_locked_or_safepoint_weak(const Monitor * lock) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// a stronger assertion than the above
|
// a stronger assertion than the above
|
||||||
void assert_lock_strong(const Monitor * lock) {
|
void assert_lock_strong(const Mutex* lock) {
|
||||||
if (IgnoreLockingAssertions) return;
|
if (IgnoreLockingAssertions) return;
|
||||||
assert(lock != NULL, "Need non-NULL lock");
|
assert(lock != NULL, "Need non-NULL lock");
|
||||||
if (lock->owned_by_self()) return;
|
if (lock->owned_by_self()) return;
|
||||||
|
@ -225,7 +225,7 @@ void mutex_init() {
|
||||||
}
|
}
|
||||||
def(ParGCRareEvent_lock , PaddedMutex , leaf , true, Monitor::_safepoint_check_always);
|
def(ParGCRareEvent_lock , PaddedMutex , leaf , true, Monitor::_safepoint_check_always);
|
||||||
def(CGCPhaseManager_lock , PaddedMonitor, leaf, false, Monitor::_safepoint_check_always);
|
def(CGCPhaseManager_lock , PaddedMonitor, leaf, false, Monitor::_safepoint_check_always);
|
||||||
def(CodeCache_lock , PaddedMutex , special, true, Monitor::_safepoint_check_never);
|
def(CodeCache_lock , PaddedMonitor, special, true, Monitor::_safepoint_check_never);
|
||||||
def(RawMonitor_lock , PaddedMutex , special, true, Monitor::_safepoint_check_never);
|
def(RawMonitor_lock , PaddedMutex , special, true, Monitor::_safepoint_check_never);
|
||||||
def(OopMapCacheAlloc_lock , PaddedMutex , leaf, true, Monitor::_safepoint_check_always); // used for oop_map_cache allocation.
|
def(OopMapCacheAlloc_lock , PaddedMutex , leaf, true, Monitor::_safepoint_check_always); // used for oop_map_cache allocation.
|
||||||
|
|
||||||
|
@ -334,7 +334,7 @@ void mutex_init() {
|
||||||
#endif // INCLUDE_CDS
|
#endif // INCLUDE_CDS
|
||||||
}
|
}
|
||||||
|
|
||||||
GCMutexLocker::GCMutexLocker(Monitor * mutex) {
|
GCMutexLocker::GCMutexLocker(Mutex* mutex) {
|
||||||
if (SafepointSynchronize::is_at_safepoint()) {
|
if (SafepointSynchronize::is_at_safepoint()) {
|
||||||
_locked = false;
|
_locked = false;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -142,7 +142,7 @@ extern Mutex* MetaspaceExpand_lock; // protects Metaspace virtualsp
|
||||||
extern Mutex* ClassLoaderDataGraph_lock; // protects CLDG list, needed for concurrent unloading
|
extern Mutex* ClassLoaderDataGraph_lock; // protects CLDG list, needed for concurrent unloading
|
||||||
|
|
||||||
|
|
||||||
extern Monitor* CodeHeapStateAnalytics_lock; // lock print functions against concurrent analyze functions.
|
extern Mutex* CodeHeapStateAnalytics_lock; // lock print functions against concurrent analyze functions.
|
||||||
// Only used locally in PrintCodeCacheLayout processing.
|
// Only used locally in PrintCodeCacheLayout processing.
|
||||||
|
|
||||||
#if INCLUDE_JVMCI
|
#if INCLUDE_JVMCI
|
||||||
|
@ -171,9 +171,9 @@ char *lock_name(Mutex *mutex);
|
||||||
|
|
||||||
// for debugging: check that we're already owning this lock (or are at a safepoint)
|
// for debugging: check that we're already owning this lock (or are at a safepoint)
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
void assert_locked_or_safepoint(const Monitor * lock);
|
void assert_locked_or_safepoint(const Mutex* lock);
|
||||||
void assert_locked_or_safepoint_weak(const Monitor * lock);
|
void assert_locked_or_safepoint_weak(const Mutex* lock);
|
||||||
void assert_lock_strong(const Monitor * lock);
|
void assert_lock_strong(const Mutex* lock);
|
||||||
#else
|
#else
|
||||||
#define assert_locked_or_safepoint(lock)
|
#define assert_locked_or_safepoint(lock)
|
||||||
#define assert_locked_or_safepoint_weak(lock)
|
#define assert_locked_or_safepoint_weak(lock)
|
||||||
|
@ -182,10 +182,10 @@ void assert_lock_strong(const Monitor * lock);
|
||||||
|
|
||||||
class MutexLocker: public StackObj {
|
class MutexLocker: public StackObj {
|
||||||
protected:
|
protected:
|
||||||
Monitor* _mutex;
|
Mutex* _mutex;
|
||||||
private:
|
private:
|
||||||
public:
|
public:
|
||||||
MutexLocker(Monitor* mutex, Mutex::SafepointCheckFlag flag = Mutex::_safepoint_check_flag) :
|
MutexLocker(Mutex* mutex, Mutex::SafepointCheckFlag flag = Mutex::_safepoint_check_flag) :
|
||||||
_mutex(mutex) {
|
_mutex(mutex) {
|
||||||
bool no_safepoint_check = flag == Mutex::_no_safepoint_check_flag;
|
bool no_safepoint_check = flag == Mutex::_no_safepoint_check_flag;
|
||||||
if (_mutex != NULL) {
|
if (_mutex != NULL) {
|
||||||
|
@ -199,7 +199,7 @@ class MutexLocker: public StackObj {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MutexLocker(Monitor* mutex, Thread* thread, Mutex::SafepointCheckFlag flag = Mutex::_safepoint_check_flag) :
|
MutexLocker(Mutex* mutex, Thread* thread, Mutex::SafepointCheckFlag flag = Mutex::_safepoint_check_flag) :
|
||||||
_mutex(mutex) {
|
_mutex(mutex) {
|
||||||
bool no_safepoint_check = flag == Mutex::_no_safepoint_check_flag;
|
bool no_safepoint_check = flag == Mutex::_no_safepoint_check_flag;
|
||||||
if (_mutex != NULL) {
|
if (_mutex != NULL) {
|
||||||
|
@ -227,35 +227,36 @@ class MutexLocker: public StackObj {
|
||||||
|
|
||||||
class MonitorLocker: public MutexLocker {
|
class MonitorLocker: public MutexLocker {
|
||||||
Mutex::SafepointCheckFlag _flag;
|
Mutex::SafepointCheckFlag _flag;
|
||||||
|
Monitor* _monitor;
|
||||||
public:
|
public:
|
||||||
MonitorLocker(Monitor* monitor, Mutex::SafepointCheckFlag flag = Mutex::_safepoint_check_flag) :
|
MonitorLocker(Monitor* monitor, Mutex::SafepointCheckFlag flag = Mutex::_safepoint_check_flag) :
|
||||||
MutexLocker(monitor, flag), _flag(flag) {
|
MutexLocker(monitor, flag), _flag(flag), _monitor(monitor) {
|
||||||
// Superclass constructor did locking
|
// Superclass constructor did locking
|
||||||
assert(_mutex != NULL, "NULL monitor not allowed");
|
assert(_monitor != NULL, "NULL monitor not allowed");
|
||||||
}
|
}
|
||||||
|
|
||||||
MonitorLocker(Monitor* monitor, Thread* thread, Mutex::SafepointCheckFlag flag = Mutex::_safepoint_check_flag) :
|
MonitorLocker(Monitor* monitor, Thread* thread, Mutex::SafepointCheckFlag flag = Mutex::_safepoint_check_flag) :
|
||||||
MutexLocker(monitor, thread, flag), _flag(flag) {
|
MutexLocker(monitor, thread, flag), _flag(flag), _monitor(monitor) {
|
||||||
// Superclass constructor did locking
|
// Superclass constructor did locking
|
||||||
assert(_mutex != NULL, "NULL monitor not allowed");
|
assert(_monitor != NULL, "NULL monitor not allowed");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wait(long timeout = 0,
|
bool wait(long timeout = 0,
|
||||||
bool as_suspend_equivalent = !Mutex::_as_suspend_equivalent_flag) {
|
bool as_suspend_equivalent = !Mutex::_as_suspend_equivalent_flag) {
|
||||||
if (_flag == Mutex::_safepoint_check_flag) {
|
if (_flag == Mutex::_safepoint_check_flag) {
|
||||||
return _mutex->wait(timeout, as_suspend_equivalent);
|
return _monitor->wait(timeout, as_suspend_equivalent);
|
||||||
} else {
|
} else {
|
||||||
return _mutex->wait_without_safepoint_check(timeout);
|
return _monitor->wait_without_safepoint_check(timeout);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void notify_all() {
|
void notify_all() {
|
||||||
_mutex->notify_all();
|
_monitor->notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
void notify() {
|
void notify() {
|
||||||
_mutex->notify();
|
_monitor->notify();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -268,10 +269,10 @@ class MonitorLocker: public MutexLocker {
|
||||||
|
|
||||||
class GCMutexLocker: public StackObj {
|
class GCMutexLocker: public StackObj {
|
||||||
private:
|
private:
|
||||||
Monitor* _mutex;
|
Mutex* _mutex;
|
||||||
bool _locked;
|
bool _locked;
|
||||||
public:
|
public:
|
||||||
GCMutexLocker(Monitor* mutex);
|
GCMutexLocker(Mutex* mutex);
|
||||||
~GCMutexLocker() { if (_locked) _mutex->unlock(); }
|
~GCMutexLocker() { if (_locked) _mutex->unlock(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -280,11 +281,11 @@ public:
|
||||||
|
|
||||||
class MutexUnlocker: StackObj {
|
class MutexUnlocker: StackObj {
|
||||||
private:
|
private:
|
||||||
Monitor* _mutex;
|
Mutex* _mutex;
|
||||||
bool _no_safepoint_check;
|
bool _no_safepoint_check;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MutexUnlocker(Monitor* mutex, Mutex::SafepointCheckFlag flag = Mutex::_safepoint_check_flag) :
|
MutexUnlocker(Mutex* mutex, Mutex::SafepointCheckFlag flag = Mutex::_safepoint_check_flag) :
|
||||||
_mutex(mutex),
|
_mutex(mutex),
|
||||||
_no_safepoint_check(flag) {
|
_no_safepoint_check(flag) {
|
||||||
_mutex->unlock();
|
_mutex->unlock();
|
||||||
|
|
|
@ -971,7 +971,7 @@ void Thread::print_value_on(outputStream* st) const {
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
void Thread::print_owned_locks_on(outputStream* st) const {
|
void Thread::print_owned_locks_on(outputStream* st) const {
|
||||||
Monitor *cur = _owned_locks;
|
Mutex* cur = _owned_locks;
|
||||||
if (cur == NULL) {
|
if (cur == NULL) {
|
||||||
st->print(" (no locks) ");
|
st->print(" (no locks) ");
|
||||||
} else {
|
} else {
|
||||||
|
@ -1011,7 +1011,7 @@ void Thread::check_for_valid_safepoint_state(bool potential_vm_operation) {
|
||||||
if (potential_vm_operation && !Universe::is_bootstrapping()) {
|
if (potential_vm_operation && !Universe::is_bootstrapping()) {
|
||||||
// Make sure we do not hold any locks that the VM thread also uses.
|
// Make sure we do not hold any locks that the VM thread also uses.
|
||||||
// This could potentially lead to deadlocks
|
// This could potentially lead to deadlocks
|
||||||
for (Monitor *cur = _owned_locks; cur; cur = cur->next()) {
|
for (Mutex* cur = _owned_locks; cur; cur = cur->next()) {
|
||||||
// Threads_lock is special, since the safepoint synchronization will not start before this is
|
// Threads_lock is special, since the safepoint synchronization will not start before this is
|
||||||
// acquired. Hence, a JavaThread cannot be holding it at a safepoint. So is VMOperationRequest_lock,
|
// acquired. Hence, a JavaThread cannot be holding it at a safepoint. So is VMOperationRequest_lock,
|
||||||
// since it is used to transfer control between JavaThreads and the VMThread
|
// since it is used to transfer control between JavaThreads and the VMThread
|
||||||
|
|
|
@ -736,7 +736,7 @@ protected:
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
private:
|
private:
|
||||||
// Deadlock detection support for Mutex locks. List of locks own by thread.
|
// Deadlock detection support for Mutex locks. List of locks own by thread.
|
||||||
Monitor* _owned_locks;
|
Mutex* _owned_locks;
|
||||||
// Mutex::set_owner_implementation is the only place where _owned_locks is modified,
|
// Mutex::set_owner_implementation is the only place where _owned_locks is modified,
|
||||||
// thus the friendship
|
// thus the friendship
|
||||||
friend class Mutex;
|
friend class Mutex;
|
||||||
|
@ -745,7 +745,7 @@ protected:
|
||||||
public:
|
public:
|
||||||
void print_owned_locks_on(outputStream* st) const;
|
void print_owned_locks_on(outputStream* st) const;
|
||||||
void print_owned_locks() const { print_owned_locks_on(tty); }
|
void print_owned_locks() const { print_owned_locks_on(tty); }
|
||||||
Monitor* owned_locks() const { return _owned_locks; }
|
Mutex* owned_locks() const { return _owned_locks; }
|
||||||
bool owns_locks() const { return owned_locks() != NULL; }
|
bool owns_locks() const { return owned_locks() != NULL; }
|
||||||
|
|
||||||
// Deadlock detection
|
// Deadlock detection
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue