mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
8226228: Make Threads_lock an always safepoint checked lock
Reviewed-by: coleenp, dcubed, dholmes
This commit is contained in:
parent
98fb7b85e5
commit
c6446d44b7
10 changed files with 32 additions and 20 deletions
|
@ -516,7 +516,7 @@ void JfrThreadSampler::task_stacktrace(JfrSampleType type, JavaThread** last_thr
|
||||||
elapsedTimer sample_time;
|
elapsedTimer sample_time;
|
||||||
sample_time.start();
|
sample_time.start();
|
||||||
{
|
{
|
||||||
MutexLocker tlock(Threads_lock, Mutex::_no_safepoint_check_flag);
|
MutexLocker tlock(Threads_lock);
|
||||||
ThreadsListHandle tlh;
|
ThreadsListHandle tlh;
|
||||||
// Resolve a sample session relative start position index into the thread list array.
|
// Resolve a sample session relative start position index into the thread list array.
|
||||||
// In cases where the last sampled thread is NULL or not-NULL but stale, find_index() returns -1.
|
// In cases where the last sampled thread is NULL or not-NULL but stale, find_index() returns -1.
|
||||||
|
|
|
@ -4135,14 +4135,13 @@ static jint attach_current_thread(JavaVM *vm, void **penv, void *_args, bool dae
|
||||||
|
|
||||||
thread->cache_global_variables();
|
thread->cache_global_variables();
|
||||||
|
|
||||||
// Crucial that we do not have a safepoint check for this thread, since it has
|
// This thread will not do a safepoint check, since it has
|
||||||
// not been added to the Thread list yet.
|
// not been added to the Thread list yet.
|
||||||
{ Threads_lock->lock_without_safepoint_check();
|
{ MutexLocker ml(Threads_lock);
|
||||||
// This must be inside this lock in order to get FullGCALot to work properly, i.e., to
|
// This must be inside this lock in order to get FullGCALot to work properly, i.e., to
|
||||||
// avoid this thread trying to do a GC before it is added to the thread-list
|
// avoid this thread trying to do a GC before it is added to the thread-list
|
||||||
thread->set_active_handles(JNIHandleBlock::allocate_block());
|
thread->set_active_handles(JNIHandleBlock::allocate_block());
|
||||||
Threads::add(thread, daemon);
|
Threads::add(thread, daemon);
|
||||||
Threads_lock->unlock();
|
|
||||||
}
|
}
|
||||||
// Create thread group and name info from attach arguments
|
// Create thread group and name info from attach arguments
|
||||||
oop group = NULL;
|
oop group = NULL;
|
||||||
|
|
|
@ -137,7 +137,7 @@ class VM_HandshakeOneThread: public VM_Handshake {
|
||||||
// There is an assumption in the code that the Threads_lock should be
|
// There is an assumption in the code that the Threads_lock should be
|
||||||
// locked during certain phases.
|
// locked during certain phases.
|
||||||
{
|
{
|
||||||
MutexLocker ml(Threads_lock, Mutex::_no_safepoint_check_flag);
|
MutexLocker ml(Threads_lock);
|
||||||
_target->handshake_process_by_vmthread();
|
_target->handshake_process_by_vmthread();
|
||||||
}
|
}
|
||||||
} while (!poll_for_completed_thread());
|
} while (!poll_for_completed_thread());
|
||||||
|
@ -186,7 +186,7 @@ class VM_HandshakeAllThreads: public VM_Handshake {
|
||||||
// There is an assumption in the code that the Threads_lock should
|
// There is an assumption in the code that the Threads_lock should
|
||||||
// be locked during certain phases.
|
// be locked during certain phases.
|
||||||
jtiwh.rewind();
|
jtiwh.rewind();
|
||||||
MutexLocker ml(Threads_lock, Mutex::_no_safepoint_check_flag);
|
MutexLocker ml(Threads_lock);
|
||||||
for (JavaThread *thr = jtiwh.next(); thr != NULL; thr = jtiwh.next()) {
|
for (JavaThread *thr = jtiwh.next(); thr != NULL; thr = jtiwh.next()) {
|
||||||
// A new thread on the ThreadsList will not have an operation,
|
// A new thread on the ThreadsList will not have an operation,
|
||||||
// hence it is skipped in handshake_process_by_vmthread.
|
// hence it is skipped in handshake_process_by_vmthread.
|
||||||
|
|
|
@ -37,7 +37,7 @@ void Monitor::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 ? Monitor::_safepoint_check_never :
|
||||||
Monitor::_safepoint_check_always;
|
Monitor::_safepoint_check_always;
|
||||||
assert(!thread->is_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());
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ void Monitor::lock(Thread * self) {
|
||||||
|
|
||||||
#ifdef CHECK_UNHANDLED_OOPS
|
#ifdef CHECK_UNHANDLED_OOPS
|
||||||
// Clear unhandled oops in JavaThreads so we get a crash right away.
|
// Clear unhandled oops in JavaThreads so we get a crash right away.
|
||||||
if (self->is_Java_thread()) {
|
if (self->is_active_Java_thread()) {
|
||||||
self->clear_unhandled_oops();
|
self->clear_unhandled_oops();
|
||||||
}
|
}
|
||||||
#endif // CHECK_UNHANDLED_OOPS
|
#endif // CHECK_UNHANDLED_OOPS
|
||||||
|
@ -62,6 +62,7 @@ void Monitor::lock(Thread * self) {
|
||||||
|
|
||||||
Monitor* in_flight_monitor = NULL;
|
Monitor* in_flight_monitor = NULL;
|
||||||
DEBUG_ONLY(int retry_cnt = 0;)
|
DEBUG_ONLY(int retry_cnt = 0;)
|
||||||
|
bool is_active_Java_thread = self->is_active_Java_thread();
|
||||||
while (!_lock.try_lock()) {
|
while (!_lock.try_lock()) {
|
||||||
// The lock is contended
|
// The lock is contended
|
||||||
|
|
||||||
|
@ -72,7 +73,8 @@ void Monitor::lock(Thread * self) {
|
||||||
}
|
}
|
||||||
#endif // ASSERT
|
#endif // ASSERT
|
||||||
|
|
||||||
if (self->is_Java_thread()) {
|
// 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");
|
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_monitor);
|
||||||
in_flight_monitor = this; // save for ~ThreadBlockInVMWithDeadlockCheck
|
in_flight_monitor = this; // save for ~ThreadBlockInVMWithDeadlockCheck
|
||||||
|
@ -190,8 +192,8 @@ bool Monitor::wait(long timeout, bool as_suspend_equivalent) {
|
||||||
|
|
||||||
assert_owner(self);
|
assert_owner(self);
|
||||||
|
|
||||||
// Safepoint checking logically implies java_thread
|
// Safepoint checking logically implies an active JavaThread.
|
||||||
guarantee(self->is_Java_thread(), "invariant");
|
guarantee(self->is_active_Java_thread(), "invariant");
|
||||||
assert_wait_lock_state(self);
|
assert_wait_lock_state(self);
|
||||||
|
|
||||||
#ifdef CHECK_UNHANDLED_OOPS
|
#ifdef CHECK_UNHANDLED_OOPS
|
||||||
|
@ -470,7 +472,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 Monitor::check_prelock_state(Thread *thread, bool safepoint_check) {
|
||||||
if (safepoint_check) {
|
if (safepoint_check) {
|
||||||
assert((!thread->is_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");
|
||||||
if (thread->is_VM_thread() && !allow_vm_block()) {
|
if (thread->is_VM_thread() && !allow_vm_block()) {
|
||||||
fatal("VM thread using lock %s (not allowed to block on)", name());
|
fatal("VM thread using lock %s (not allowed to block on)", name());
|
||||||
|
|
|
@ -287,7 +287,7 @@ void mutex_init() {
|
||||||
// CMS_bitMap_lock leaf 1
|
// CMS_bitMap_lock leaf 1
|
||||||
// CMS_freeList_lock leaf 2
|
// CMS_freeList_lock leaf 2
|
||||||
|
|
||||||
def(Threads_lock , PaddedMonitor, barrier, true, Monitor::_safepoint_check_sometimes); // Used for safepoint protocol.
|
def(Threads_lock , PaddedMonitor, barrier, true, Monitor::_safepoint_check_always); // Used for safepoint protocol.
|
||||||
def(NonJavaThreadsList_lock , PaddedMutex, leaf, true, Monitor::_safepoint_check_never);
|
def(NonJavaThreadsList_lock , PaddedMutex, leaf, true, Monitor::_safepoint_check_never);
|
||||||
def(NonJavaThreadsListSync_lock , PaddedMutex, leaf, true, Monitor::_safepoint_check_never);
|
def(NonJavaThreadsListSync_lock , PaddedMutex, leaf, true, Monitor::_safepoint_check_never);
|
||||||
|
|
||||||
|
|
|
@ -1804,7 +1804,7 @@ void JavaThread::block_if_vm_exited() {
|
||||||
if (_terminated == _vm_exited) {
|
if (_terminated == _vm_exited) {
|
||||||
// _vm_exited is set at safepoint, and Threads_lock is never released
|
// _vm_exited is set at safepoint, and Threads_lock is never released
|
||||||
// we will block here forever
|
// we will block here forever
|
||||||
Threads_lock->lock_without_safepoint_check();
|
Threads_lock->lock();
|
||||||
ShouldNotReachHere();
|
ShouldNotReachHere();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -491,6 +491,10 @@ class Thread: public ThreadShadow {
|
||||||
// Can this thread make Java upcalls
|
// Can this thread make Java upcalls
|
||||||
virtual bool can_call_java() const { return false; }
|
virtual bool can_call_java() const { return false; }
|
||||||
|
|
||||||
|
// Is this a JavaThread that is on the VM's current ThreadsList?
|
||||||
|
// If so it must participate in the safepoint protocol.
|
||||||
|
virtual bool is_active_Java_thread() const { return false; }
|
||||||
|
|
||||||
// Casts
|
// Casts
|
||||||
virtual WorkerThread* as_Worker_thread() const { return NULL; }
|
virtual WorkerThread* as_Worker_thread() const { return NULL; }
|
||||||
|
|
||||||
|
@ -1247,6 +1251,10 @@ class JavaThread: public Thread {
|
||||||
virtual bool is_Java_thread() const { return true; }
|
virtual bool is_Java_thread() const { return true; }
|
||||||
virtual bool can_call_java() const { return true; }
|
virtual bool can_call_java() const { return true; }
|
||||||
|
|
||||||
|
virtual bool is_active_Java_thread() const {
|
||||||
|
return on_thread_list() && !is_terminated();
|
||||||
|
}
|
||||||
|
|
||||||
// Thread oop. threadObj() can be NULL for initial JavaThread
|
// Thread oop. threadObj() can be NULL for initial JavaThread
|
||||||
// (or for threads attached via JNI)
|
// (or for threads attached via JNI)
|
||||||
oop threadObj() const { return _threadObj; }
|
oop threadObj() const { return _threadObj; }
|
||||||
|
|
|
@ -942,9 +942,9 @@ void ThreadsSMRSupport::smr_delete(JavaThread *thread) {
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
{
|
{
|
||||||
// No safepoint check because this JavaThread is not on the
|
// Will not make a safepoint check because this JavaThread
|
||||||
// Threads list.
|
// is not on the current ThreadsList.
|
||||||
MutexLocker ml(Threads_lock, Mutex::_no_safepoint_check_flag);
|
MutexLocker ml(Threads_lock);
|
||||||
// Cannot use a MonitorLocker helper here because we have
|
// Cannot use a MonitorLocker helper here because we have
|
||||||
// to drop the Threads_lock first if we wait.
|
// to drop the Threads_lock first if we wait.
|
||||||
ThreadsSMRSupport::delete_lock()->lock_without_safepoint_check();
|
ThreadsSMRSupport::delete_lock()->lock_without_safepoint_check();
|
||||||
|
|
|
@ -522,7 +522,7 @@ void VM_Exit::wait_if_vm_exited() {
|
||||||
Thread::current_or_null() != _shutdown_thread) {
|
Thread::current_or_null() != _shutdown_thread) {
|
||||||
// _vm_exited is set at safepoint, and the Threads_lock is never released
|
// _vm_exited is set at safepoint, and the Threads_lock is never released
|
||||||
// we will block here until the process dies
|
// we will block here until the process dies
|
||||||
Threads_lock->lock_without_safepoint_check();
|
Threads_lock->lock();
|
||||||
ShouldNotReachHere();
|
ShouldNotReachHere();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1797,11 +1797,14 @@ void VMError::controlled_crash(int how) {
|
||||||
// Case 16 is tested by test/hotspot/jtreg/runtime/ErrorHandling/ThreadsListHandleInErrorHandlingTest.java.
|
// Case 16 is tested by test/hotspot/jtreg/runtime/ErrorHandling/ThreadsListHandleInErrorHandlingTest.java.
|
||||||
// Case 17 is tested by test/hotspot/jtreg/runtime/ErrorHandling/NestedThreadsListHandleInErrorHandlingTest.java.
|
// Case 17 is tested by test/hotspot/jtreg/runtime/ErrorHandling/NestedThreadsListHandleInErrorHandlingTest.java.
|
||||||
|
|
||||||
// We grab Threads_lock to keep ThreadsSMRSupport::print_info_on()
|
// We try to grab Threads_lock to keep ThreadsSMRSupport::print_info_on()
|
||||||
// from racing with Threads::add() or Threads::remove() as we
|
// from racing with Threads::add() or Threads::remove() as we
|
||||||
// generate the hs_err_pid file. This makes our ErrorHandling tests
|
// generate the hs_err_pid file. This makes our ErrorHandling tests
|
||||||
// more stable.
|
// more stable.
|
||||||
MutexLocker ml(Threads_lock->owned_by_self() ? NULL : Threads_lock, Mutex::_no_safepoint_check_flag);
|
if (!Threads_lock->owned_by_self()) {
|
||||||
|
Threads_lock->try_lock();
|
||||||
|
// The VM is going to die so no need to unlock Thread_lock.
|
||||||
|
}
|
||||||
|
|
||||||
switch (how) {
|
switch (how) {
|
||||||
case 1: vmassert(str == NULL, "expected null"); break;
|
case 1: vmassert(str == NULL, "expected null"); break;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue