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
@ -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
|
||||
// we see a consistent picture and do not run into issues caused by
|
||||
// the CodeHeap being altered concurrently.
|
||||
Monitor* global_lock = allFun ? CodeCache_lock : NULL;
|
||||
Monitor* function_lock = allFun ? NULL : CodeCache_lock;
|
||||
Mutex* global_lock = allFun ? CodeCache_lock : NULL;
|
||||
Mutex* function_lock = allFun ? NULL : CodeCache_lock;
|
||||
ts_global.update(); // record starting point
|
||||
MutexLocker mu2(global_lock, Mutex::_no_safepoint_check_flag);
|
||||
if (global_lock != NULL) {
|
||||
|
@ -356,9 +356,9 @@ static void prepare_for_emergency_dump(Thread* thread) {
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
Monitor* owned_lock = thread->owned_locks();
|
||||
Mutex* owned_lock = thread->owned_locks();
|
||||
while (owned_lock != NULL) {
|
||||
Monitor* next = owned_lock->next();
|
||||
Mutex* next = owned_lock->next();
|
||||
owned_lock->unlock();
|
||||
owned_lock = next;
|
||||
}
|
||||
|
@ -171,7 +171,7 @@
|
||||
LOG_TAG(mirror) \
|
||||
LOG_TAG(verification) \
|
||||
LOG_TAG(verify) \
|
||||
LOG_TAG(vmmonitor) \
|
||||
LOG_TAG(vmmutex) \
|
||||
LOG_TAG(vmoperation) \
|
||||
LOG_TAG(vmthread) \
|
||||
LOG_TAG(vtables) \
|
||||
|
@ -254,30 +254,30 @@ class ThreadBlockInVM : public ThreadStateTransition {
|
||||
};
|
||||
|
||||
// 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
|
||||
// receives an extra argument compared to ThreadBlockInVM, the address of a pointer to the monitor we
|
||||
// are trying to acquire. This will be used to access and release the monitor if needed to avoid
|
||||
// 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 mutex we
|
||||
// are trying to acquire. This will be used to access and release the mutex if needed to avoid
|
||||
// said deadlocks.
|
||||
// It works like ThreadBlockInVM but differs from it in two ways:
|
||||
// - 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.
|
||||
// - 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 {
|
||||
private:
|
||||
Monitor** _in_flight_monitor_adr;
|
||||
Mutex** _in_flight_mutex_addr;
|
||||
|
||||
void release_monitor() {
|
||||
assert(_in_flight_monitor_adr != NULL, "_in_flight_monitor_adr should have been set on constructor");
|
||||
Monitor* in_flight_monitor = *_in_flight_monitor_adr;
|
||||
if (in_flight_monitor != NULL) {
|
||||
in_flight_monitor->release_for_safepoint();
|
||||
*_in_flight_monitor_adr = NULL;
|
||||
void release_mutex() {
|
||||
assert(_in_flight_mutex_addr != NULL, "_in_flight_mutex_addr should have been set on constructor");
|
||||
Mutex* in_flight_mutex = *_in_flight_mutex_addr;
|
||||
if (in_flight_mutex != NULL) {
|
||||
in_flight_mutex->release_for_safepoint();
|
||||
*_in_flight_mutex_addr = NULL;
|
||||
}
|
||||
}
|
||||
public:
|
||||
ThreadBlockInVMWithDeadlockCheck(JavaThread* thread, Monitor** in_flight_monitor_adr)
|
||||
: ThreadStateTransition(thread), _in_flight_monitor_adr(in_flight_monitor_adr) {
|
||||
ThreadBlockInVMWithDeadlockCheck(JavaThread* thread, Mutex** in_flight_mutex_addr)
|
||||
: ThreadStateTransition(thread), _in_flight_mutex_addr(in_flight_mutex_addr) {
|
||||
// Once we are blocked vm expects stack to be walkable
|
||||
thread->frame_anchor()->make_walkable(thread);
|
||||
|
||||
@ -293,7 +293,7 @@ class ThreadBlockInVMWithDeadlockCheck : public ThreadStateTransition {
|
||||
_thread->set_thread_state_fence((JavaThreadState)(_thread_blocked_trans));
|
||||
|
||||
if (SafepointMechanism::should_block(_thread)) {
|
||||
release_monitor();
|
||||
release_mutex();
|
||||
SafepointMechanism::block_if_requested(_thread);
|
||||
}
|
||||
|
||||
|
@ -33,27 +33,27 @@
|
||||
#include "utilities/macros.hpp"
|
||||
|
||||
#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.
|
||||
SafepointCheckRequired not_allowed = do_safepoint_check ? Monitor::_safepoint_check_never :
|
||||
Monitor::_safepoint_check_always;
|
||||
SafepointCheckRequired not_allowed = do_safepoint_check ? Mutex::_safepoint_check_never :
|
||||
Mutex::_safepoint_check_always;
|
||||
assert(!thread->is_active_Java_thread() || _safepoint_check_required != not_allowed,
|
||||
"This lock should %s have a safepoint check for Java threads: %s",
|
||||
_safepoint_check_required ? "always" : "never", name());
|
||||
|
||||
// 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");
|
||||
}
|
||||
#endif // ASSERT
|
||||
|
||||
void Monitor::lock(Thread * self) {
|
||||
void Mutex::lock(Thread * self) {
|
||||
check_safepoint_state(self, true);
|
||||
|
||||
DEBUG_ONLY(check_prelock_state(self, true));
|
||||
assert(_owner != self, "invariant");
|
||||
|
||||
Monitor* in_flight_monitor = NULL;
|
||||
Mutex* in_flight_mutex = NULL;
|
||||
DEBUG_ONLY(int retry_cnt = 0;)
|
||||
bool is_active_Java_thread = self->is_active_Java_thread();
|
||||
while (!_lock.try_lock()) {
|
||||
@ -62,18 +62,18 @@ void Monitor::lock(Thread * self) {
|
||||
#ifdef ASSERT
|
||||
check_block_state(self);
|
||||
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
|
||||
|
||||
// Is it a JavaThread participating in the safepoint protocol.
|
||||
if (is_active_Java_thread) {
|
||||
assert(rank() > Mutex::special, "Potential deadlock with special or lesser rank mutex");
|
||||
{ ThreadBlockInVMWithDeadlockCheck tbivmdc((JavaThread *) self, &in_flight_monitor);
|
||||
in_flight_monitor = this; // save for ~ThreadBlockInVMWithDeadlockCheck
|
||||
{ ThreadBlockInVMWithDeadlockCheck tbivmdc((JavaThread *) self, &in_flight_mutex);
|
||||
in_flight_mutex = this; // save for ~ThreadBlockInVMWithDeadlockCheck
|
||||
_lock.lock();
|
||||
}
|
||||
if (in_flight_monitor != NULL) {
|
||||
if (in_flight_mutex != NULL) {
|
||||
// Not unlocked by ~ThreadBlockInVMWithDeadlockCheck
|
||||
break;
|
||||
}
|
||||
@ -87,7 +87,7 @@ void Monitor::lock(Thread * self) {
|
||||
set_owner(self);
|
||||
}
|
||||
|
||||
void Monitor::lock() {
|
||||
void Mutex::lock() {
|
||||
this->lock(Thread::current());
|
||||
}
|
||||
|
||||
@ -97,7 +97,7 @@ void Monitor::lock() {
|
||||
// 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.
|
||||
|
||||
void Monitor::lock_without_safepoint_check(Thread * self) {
|
||||
void Mutex::lock_without_safepoint_check(Thread * self) {
|
||||
check_safepoint_state(self, false);
|
||||
assert(_owner != self, "invariant");
|
||||
_lock.lock();
|
||||
@ -105,14 +105,14 @@ void Monitor::lock_without_safepoint_check(Thread * self) {
|
||||
set_owner(self);
|
||||
}
|
||||
|
||||
void Monitor::lock_without_safepoint_check() {
|
||||
void Mutex::lock_without_safepoint_check() {
|
||||
lock_without_safepoint_check(Thread::current());
|
||||
}
|
||||
|
||||
|
||||
// Returns true if thread succeeds in grabbing the lock, otherwise false.
|
||||
|
||||
bool Monitor::try_lock() {
|
||||
bool Mutex::try_lock() {
|
||||
Thread * const self = Thread::current();
|
||||
DEBUG_ONLY(check_prelock_state(self, false);)
|
||||
|
||||
@ -124,12 +124,12 @@ bool Monitor::try_lock() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void Monitor::release_for_safepoint() {
|
||||
void Mutex::release_for_safepoint() {
|
||||
assert_owner(NULL);
|
||||
_lock.unlock();
|
||||
}
|
||||
|
||||
void Monitor::unlock() {
|
||||
void Mutex::unlock() {
|
||||
assert_owner(Thread::current());
|
||||
set_owner(NULL);
|
||||
_lock.unlock();
|
||||
@ -147,7 +147,7 @@ void Monitor::notify_all() {
|
||||
|
||||
#ifdef ASSERT
|
||||
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");
|
||||
if (least != NULL && least->rank() <= special) {
|
||||
::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
|
||||
set_owner(NULL);
|
||||
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() */);
|
||||
if (as_suspend_equivalent) {
|
||||
jt->set_suspend_equivalent();
|
||||
@ -206,7 +206,7 @@ bool Monitor::wait(long timeout, bool as_suspend_equivalent) {
|
||||
}
|
||||
|
||||
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?
|
||||
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
|
||||
assert_owner(NULL);
|
||||
// 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
|
||||
}
|
||||
|
||||
Monitor::~Monitor() {
|
||||
Mutex::~Mutex() {
|
||||
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);
|
||||
}
|
||||
|
||||
Monitor::Monitor(int Rank, const char * name, bool allow_vm_block,
|
||||
SafepointCheckRequired safepoint_check_required) : _owner(NULL) {
|
||||
Mutex::Mutex(int Rank, const char * name, bool allow_vm_block,
|
||||
SafepointCheckRequired safepoint_check_required) : _owner(NULL) {
|
||||
assert(os::mutex_init_done(), "Too early!");
|
||||
if (name == NULL) {
|
||||
strcpy(_name, "UNKNOWN");
|
||||
} else {
|
||||
strncpy(_name, name, MONITOR_NAME_LEN - 1);
|
||||
_name[MONITOR_NAME_LEN - 1] = '\0';
|
||||
strncpy(_name, name, MUTEX_NAME_LEN - 1);
|
||||
_name[MUTEX_NAME_LEN - 1] = '\0';
|
||||
}
|
||||
#ifdef ASSERT
|
||||
_allow_vm_block = allow_vm_block;
|
||||
_rank = Rank;
|
||||
_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);
|
||||
#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) :
|
||||
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();
|
||||
}
|
||||
|
||||
void Monitor::print_on_error(outputStream* st) const {
|
||||
void Mutex::print_on_error(outputStream* st) const {
|
||||
st->print("[" PTR_FORMAT, p2i(this));
|
||||
st->print("] %s", _name);
|
||||
st->print(" - owner thread: " PTR_FORMAT, p2i(_owner));
|
||||
@ -278,7 +278,7 @@ void Monitor::print_on_error(outputStream* st) const {
|
||||
// Non-product code
|
||||
|
||||
#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,
|
||||
p2i(this), _name, p2i(_owner));
|
||||
}
|
||||
@ -287,7 +287,7 @@ void Monitor::print_on(outputStream* st) const {
|
||||
#ifndef PRODUCT
|
||||
#ifdef ASSERT
|
||||
|
||||
void Monitor::assert_owner(Thread * expected) {
|
||||
void Mutex::assert_owner(Thread * expected) {
|
||||
const char* msg = "invalid owner";
|
||||
if (expected == NULL) {
|
||||
msg = "should be un-owned";
|
||||
@ -300,8 +300,8 @@ void Monitor::assert_owner(Thread * expected) {
|
||||
msg, p2i(_owner), p2i(expected));
|
||||
}
|
||||
|
||||
Monitor * Monitor::get_least_ranked_lock(Monitor * locks) {
|
||||
Monitor *res, *tmp;
|
||||
Mutex* Mutex::get_least_ranked_lock(Mutex* locks) {
|
||||
Mutex *res, *tmp;
|
||||
for (res = tmp = locks; tmp != NULL; tmp = tmp->next()) {
|
||||
if (tmp->rank() < res->rank()) {
|
||||
res = tmp;
|
||||
@ -320,8 +320,8 @@ Monitor * Monitor::get_least_ranked_lock(Monitor * locks) {
|
||||
return res;
|
||||
}
|
||||
|
||||
Monitor* Monitor::get_least_ranked_lock_besides_this(Monitor* locks) {
|
||||
Monitor *res, *tmp;
|
||||
Mutex* Mutex::get_least_ranked_lock_besides_this(Mutex* locks) {
|
||||
Mutex *res, *tmp;
|
||||
for (res = NULL, tmp = locks; tmp != NULL; tmp = tmp->next()) {
|
||||
if (tmp != this && (res == NULL || tmp->rank() < res->rank())) {
|
||||
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()) {
|
||||
if (locks == lock) {
|
||||
return true;
|
||||
@ -356,7 +356,7 @@ bool Monitor::contains(Monitor* locks, Monitor * lock) {
|
||||
// might indicate exposure to deadlock.
|
||||
// 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
|
||||
// and checking the invariant that threads and locks
|
||||
// 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
|
||||
|
||||
#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
|
||||
|
||||
assert(this->rank() >= 0, "bad lock rank");
|
||||
@ -415,11 +415,11 @@ void Monitor::set_owner_implementation(Thread *new_owner) {
|
||||
_owner = NULL; // set the owner
|
||||
|
||||
#ifdef ASSERT
|
||||
Monitor *locks = old_owner->owned_locks();
|
||||
Mutex* locks = old_owner->owned_locks();
|
||||
|
||||
// remove "this" from the owned locks list
|
||||
|
||||
Monitor *prev = NULL;
|
||||
Mutex* prev = NULL;
|
||||
bool found = false;
|
||||
for (; locks != NULL; prev = locks, locks = locks->next()) {
|
||||
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()
|
||||
void Monitor::check_prelock_state(Thread *thread, bool safepoint_check) {
|
||||
void Mutex::check_prelock_state(Thread *thread, bool safepoint_check) {
|
||||
if (safepoint_check) {
|
||||
assert((!thread->is_active_Java_thread() || ((JavaThread *)thread)->thread_state() == _thread_in_vm)
|
||||
|| 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");
|
||||
}
|
||||
|
||||
void Monitor::check_block_state(Thread *thread) {
|
||||
void Mutex::check_block_state(Thread *thread) {
|
||||
if (!_allow_vm_block && thread->is_VM_thread()) {
|
||||
warning("VM thread blocked on lock");
|
||||
print();
|
||||
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
|
||||
|
@ -32,12 +32,12 @@
|
||||
// variable that supports lock ownership tracking, lock ranking for deadlock
|
||||
// detection and coordinates with the safepoint protocol.
|
||||
|
||||
// The default length of monitor name was originally chosen to be 64 to avoid
|
||||
// false sharing. Now, PaddedMonitor is available for this purpose.
|
||||
// TODO: Check if _name[MONITOR_NAME_LEN] should better get replaced by const char*.
|
||||
static const int MONITOR_NAME_LEN = 64;
|
||||
// The default length of mutex name was originally chosen to be 64 to avoid
|
||||
// false sharing. Now, PaddedMutex and PaddedMonitor are available for this purpose.
|
||||
// TODO: Check if _name[MUTEX_NAME_LEN] should better get replaced by const char*.
|
||||
static const int MUTEX_NAME_LEN = 64;
|
||||
|
||||
class Monitor : public CHeapObj<mtSynchronizer> {
|
||||
class Mutex : public CHeapObj<mtSynchronizer> {
|
||||
|
||||
public:
|
||||
// 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
|
||||
Thread * volatile _owner; // The owner of the lock
|
||||
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)
|
||||
#ifndef PRODUCT
|
||||
bool _allow_vm_block;
|
||||
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(static bool contains(Monitor * locks, Monitor * lock);)
|
||||
DEBUG_ONLY(static Monitor * get_least_ranked_lock(Monitor * locks);)
|
||||
DEBUG_ONLY(Monitor * get_least_ranked_lock_besides_this(Monitor * locks);)
|
||||
DEBUG_ONLY(static bool contains(Mutex* locks, Mutex* lock);)
|
||||
DEBUG_ONLY(static Mutex* get_least_ranked_lock(Mutex* locks);)
|
||||
DEBUG_ONLY(Mutex* get_least_ranked_lock_besides_this(Mutex* locks);)
|
||||
#endif
|
||||
|
||||
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_safepoint_state (Thread* thread, bool safepoint_check) NOT_DEBUG_RETURN;
|
||||
void assert_owner (Thread* expected) NOT_DEBUG_RETURN;
|
||||
void assert_wait_lock_state (Thread* self) NOT_DEBUG_RETURN;
|
||||
|
||||
public:
|
||||
enum {
|
||||
@ -130,32 +129,21 @@ class Monitor : public CHeapObj<mtSynchronizer> {
|
||||
};
|
||||
|
||||
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.
|
||||
_safepoint_check_sometimes, // A couple of special locks are acquired by JavaThreads sometimes
|
||||
// with and sometimes without safepoint checks. These
|
||||
// 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.
|
||||
};
|
||||
|
||||
NOT_PRODUCT(SafepointCheckRequired _safepoint_check_required;)
|
||||
|
||||
public:
|
||||
Monitor(int rank, const char *name, bool allow_vm_block = false,
|
||||
SafepointCheckRequired safepoint_check_required = _safepoint_check_always);
|
||||
~Monitor();
|
||||
|
||||
// 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();
|
||||
|
||||
Mutex(int rank, const char *name, bool allow_vm_block = false,
|
||||
SafepointCheckRequired safepoint_check_required = _safepoint_check_always);
|
||||
~Mutex();
|
||||
|
||||
void lock(); // prints out warning if VM thread blocks
|
||||
void lock(Thread *thread); // overloaded with current thread
|
||||
@ -186,19 +174,49 @@ class Monitor : public CHeapObj<mtSynchronizer> {
|
||||
DEBUG_ONLY(int rank() const { return _rank; })
|
||||
bool allow_vm_block() { return _allow_vm_block; }
|
||||
|
||||
DEBUG_ONLY(Monitor *next() const { return _next; })
|
||||
DEBUG_ONLY(void set_next(Monitor *next) { _next = next; })
|
||||
DEBUG_ONLY(Mutex *next() const { return _next; })
|
||||
DEBUG_ONLY(void set_next(Mutex *next) { _next = next; })
|
||||
#endif
|
||||
|
||||
void set_owner(Thread* owner) {
|
||||
#ifndef PRODUCT
|
||||
set_owner_implementation(owner);
|
||||
DEBUG_ONLY(void verify_Monitor(Thread* thr);)
|
||||
DEBUG_ONLY(void verify_mutex(Thread* thr);)
|
||||
#else
|
||||
_owner = owner;
|
||||
#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 {
|
||||
@ -213,49 +231,4 @@ class PaddedMonitor : public Monitor {
|
||||
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
|
||||
|
@ -130,7 +130,7 @@ Monitor* JfrThreadSampler_lock = NULL;
|
||||
#ifndef SUPPORTS_NATIVE_CX8
|
||||
Mutex* UnsafeJlong_lock = NULL;
|
||||
#endif
|
||||
Monitor* CodeHeapStateAnalytics_lock = NULL;
|
||||
Mutex* CodeHeapStateAnalytics_lock = NULL;
|
||||
|
||||
Mutex* MetaspaceExpand_lock = NULL;
|
||||
Mutex* ClassLoaderDataGraph_lock = NULL;
|
||||
@ -153,11 +153,11 @@ Monitor* JVMCI_lock = NULL;
|
||||
|
||||
|
||||
#define MAX_NUM_MUTEX 128
|
||||
static Monitor * _mutex_array[MAX_NUM_MUTEX];
|
||||
static Mutex* _mutex_array[MAX_NUM_MUTEX];
|
||||
static int _num_mutex;
|
||||
|
||||
#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)
|
||||
if (IgnoreLockingAssertions) return;
|
||||
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
|
||||
void assert_locked_or_safepoint_weak(const Monitor * lock) {
|
||||
void assert_locked_or_safepoint_weak(const Mutex* lock) {
|
||||
if (IgnoreLockingAssertions) return;
|
||||
assert(lock != NULL, "Need non-NULL lock");
|
||||
if (lock->is_locked()) return;
|
||||
@ -181,7 +181,7 @@ void assert_locked_or_safepoint_weak(const Monitor * lock) {
|
||||
}
|
||||
|
||||
// a stronger assertion than the above
|
||||
void assert_lock_strong(const Monitor * lock) {
|
||||
void assert_lock_strong(const Mutex* lock) {
|
||||
if (IgnoreLockingAssertions) return;
|
||||
assert(lock != NULL, "Need non-NULL lock");
|
||||
if (lock->owned_by_self()) return;
|
||||
@ -225,7 +225,7 @@ void mutex_init() {
|
||||
}
|
||||
def(ParGCRareEvent_lock , PaddedMutex , leaf , true, 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(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
|
||||
}
|
||||
|
||||
GCMutexLocker::GCMutexLocker(Monitor * mutex) {
|
||||
GCMutexLocker::GCMutexLocker(Mutex* mutex) {
|
||||
if (SafepointSynchronize::is_at_safepoint()) {
|
||||
_locked = false;
|
||||
} else {
|
||||
|
@ -142,7 +142,7 @@ extern Mutex* MetaspaceExpand_lock; // protects Metaspace virtualsp
|
||||
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.
|
||||
|
||||
#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)
|
||||
#ifdef ASSERT
|
||||
void assert_locked_or_safepoint(const Monitor * lock);
|
||||
void assert_locked_or_safepoint_weak(const Monitor * lock);
|
||||
void assert_lock_strong(const Monitor * lock);
|
||||
void assert_locked_or_safepoint(const Mutex* lock);
|
||||
void assert_locked_or_safepoint_weak(const Mutex* lock);
|
||||
void assert_lock_strong(const Mutex* lock);
|
||||
#else
|
||||
#define assert_locked_or_safepoint(lock)
|
||||
#define assert_locked_or_safepoint_weak(lock)
|
||||
@ -182,10 +182,10 @@ void assert_lock_strong(const Monitor * lock);
|
||||
|
||||
class MutexLocker: public StackObj {
|
||||
protected:
|
||||
Monitor* _mutex;
|
||||
Mutex* _mutex;
|
||||
private:
|
||||
public:
|
||||
MutexLocker(Monitor* mutex, Mutex::SafepointCheckFlag flag = Mutex::_safepoint_check_flag) :
|
||||
MutexLocker(Mutex* mutex, Mutex::SafepointCheckFlag flag = Mutex::_safepoint_check_flag) :
|
||||
_mutex(mutex) {
|
||||
bool no_safepoint_check = flag == Mutex::_no_safepoint_check_flag;
|
||||
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) {
|
||||
bool no_safepoint_check = flag == Mutex::_no_safepoint_check_flag;
|
||||
if (_mutex != NULL) {
|
||||
@ -227,35 +227,36 @@ class MutexLocker: public StackObj {
|
||||
|
||||
class MonitorLocker: public MutexLocker {
|
||||
Mutex::SafepointCheckFlag _flag;
|
||||
Monitor* _monitor;
|
||||
public:
|
||||
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
|
||||
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) :
|
||||
MutexLocker(monitor, thread, flag), _flag(flag) {
|
||||
MutexLocker(monitor, thread, flag), _flag(flag), _monitor(monitor) {
|
||||
// Superclass constructor did locking
|
||||
assert(_mutex != NULL, "NULL monitor not allowed");
|
||||
assert(_monitor != NULL, "NULL monitor not allowed");
|
||||
}
|
||||
|
||||
bool wait(long timeout = 0,
|
||||
bool as_suspend_equivalent = !Mutex::_as_suspend_equivalent_flag) {
|
||||
if (_flag == Mutex::_safepoint_check_flag) {
|
||||
return _mutex->wait(timeout, as_suspend_equivalent);
|
||||
return _monitor->wait(timeout, as_suspend_equivalent);
|
||||
} else {
|
||||
return _mutex->wait_without_safepoint_check(timeout);
|
||||
return _monitor->wait_without_safepoint_check(timeout);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void notify_all() {
|
||||
_mutex->notify_all();
|
||||
_monitor->notify_all();
|
||||
}
|
||||
|
||||
void notify() {
|
||||
_mutex->notify();
|
||||
_monitor->notify();
|
||||
}
|
||||
};
|
||||
|
||||
@ -268,10 +269,10 @@ class MonitorLocker: public MutexLocker {
|
||||
|
||||
class GCMutexLocker: public StackObj {
|
||||
private:
|
||||
Monitor* _mutex;
|
||||
Mutex* _mutex;
|
||||
bool _locked;
|
||||
public:
|
||||
GCMutexLocker(Monitor* mutex);
|
||||
GCMutexLocker(Mutex* mutex);
|
||||
~GCMutexLocker() { if (_locked) _mutex->unlock(); }
|
||||
};
|
||||
|
||||
@ -280,11 +281,11 @@ public:
|
||||
|
||||
class MutexUnlocker: StackObj {
|
||||
private:
|
||||
Monitor* _mutex;
|
||||
Mutex* _mutex;
|
||||
bool _no_safepoint_check;
|
||||
|
||||
public:
|
||||
MutexUnlocker(Monitor* mutex, Mutex::SafepointCheckFlag flag = Mutex::_safepoint_check_flag) :
|
||||
MutexUnlocker(Mutex* mutex, Mutex::SafepointCheckFlag flag = Mutex::_safepoint_check_flag) :
|
||||
_mutex(mutex),
|
||||
_no_safepoint_check(flag) {
|
||||
_mutex->unlock();
|
||||
|
@ -971,7 +971,7 @@ void Thread::print_value_on(outputStream* st) const {
|
||||
|
||||
#ifdef ASSERT
|
||||
void Thread::print_owned_locks_on(outputStream* st) const {
|
||||
Monitor *cur = _owned_locks;
|
||||
Mutex* cur = _owned_locks;
|
||||
if (cur == NULL) {
|
||||
st->print(" (no locks) ");
|
||||
} else {
|
||||
@ -1011,7 +1011,7 @@ void Thread::check_for_valid_safepoint_state(bool potential_vm_operation) {
|
||||
if (potential_vm_operation && !Universe::is_bootstrapping()) {
|
||||
// Make sure we do not hold any locks that the VM thread also uses.
|
||||
// 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
|
||||
// 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
|
||||
|
@ -736,7 +736,7 @@ protected:
|
||||
#ifdef ASSERT
|
||||
private:
|
||||
// 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,
|
||||
// thus the friendship
|
||||
friend class Mutex;
|
||||
@ -745,7 +745,7 @@ protected:
|
||||
public:
|
||||
void print_owned_locks_on(outputStream* st) const;
|
||||
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; }
|
||||
|
||||
// Deadlock detection
|
||||
|
Loading…
Reference in New Issue
Block a user