mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 23:34:52 +02:00
8232733: Remove need to grab Threads_lock while processing handshakes
Threads_lock is not acquired anymore while processing handshakes Reviewed-by: coleenp, rehn, dcubed, dholmes
This commit is contained in:
parent
94e8d6eca4
commit
57ece4c21a
7 changed files with 37 additions and 34 deletions
|
@ -147,14 +147,7 @@ class VM_HandshakeOneThread: public VM_Handshake {
|
||||||
if (handshake_has_timed_out(timeout_start_time)) {
|
if (handshake_has_timed_out(timeout_start_time)) {
|
||||||
handle_timeout();
|
handle_timeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to re-think this with SMR ThreadsList.
|
|
||||||
// There is an assumption in the code that the Threads_lock should be
|
|
||||||
// locked during certain phases.
|
|
||||||
{
|
|
||||||
MutexLocker ml(Threads_lock);
|
|
||||||
by_vm_thread = _target->handshake_try_process_by_vmThread();
|
by_vm_thread = _target->handshake_try_process_by_vmThread();
|
||||||
}
|
|
||||||
} while (!poll_for_completed_thread());
|
} while (!poll_for_completed_thread());
|
||||||
DEBUG_ONLY(_op->check_state();)
|
DEBUG_ONLY(_op->check_state();)
|
||||||
log_handshake_info(start_time_ns, _op->name(), 1, by_vm_thread ? 1 : 0);
|
log_handshake_info(start_time_ns, _op->name(), 1, by_vm_thread ? 1 : 0);
|
||||||
|
@ -202,12 +195,7 @@ class VM_HandshakeAllThreads: public VM_Handshake {
|
||||||
// Have VM thread perform the handshake operation for blocked threads.
|
// Have VM thread perform the handshake operation for blocked threads.
|
||||||
// Observing a blocked state may of course be transient but the processing is guarded
|
// Observing a blocked state may of course be transient but the processing is guarded
|
||||||
// by semaphores and we optimistically begin by working on the blocked threads
|
// by semaphores and we optimistically begin by working on the blocked threads
|
||||||
{
|
|
||||||
// We need to re-think this with SMR ThreadsList.
|
|
||||||
// There is an assumption in the code that the Threads_lock should
|
|
||||||
// be locked during certain phases.
|
|
||||||
jtiwh.rewind();
|
jtiwh.rewind();
|
||||||
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.
|
||||||
|
@ -215,8 +203,6 @@ class VM_HandshakeAllThreads: public VM_Handshake {
|
||||||
handshake_executed_by_vm_thread++;
|
handshake_executed_by_vm_thread++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
while (poll_for_completed_thread()) {
|
while (poll_for_completed_thread()) {
|
||||||
// Includes canceled operations by exiting threads.
|
// Includes canceled operations by exiting threads.
|
||||||
number_of_threads_completed++;
|
number_of_threads_completed++;
|
||||||
|
@ -279,6 +265,8 @@ void HandshakeThreadsOperation::do_handshake(JavaThread* thread) {
|
||||||
|
|
||||||
// Use the semaphore to inform the VM thread that we have completed the operation
|
// Use the semaphore to inform the VM thread that we have completed the operation
|
||||||
_done.signal();
|
_done.signal();
|
||||||
|
|
||||||
|
// It is no longer safe to refer to 'this' as the VMThread may have destroyed this operation
|
||||||
}
|
}
|
||||||
|
|
||||||
void Handshake::execute(HandshakeClosure* thread_cl) {
|
void Handshake::execute(HandshakeClosure* thread_cl) {
|
||||||
|
@ -305,7 +293,9 @@ bool Handshake::execute(HandshakeClosure* thread_cl, JavaThread* target) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HandshakeState::HandshakeState() : _operation(NULL), _semaphore(1), _thread_in_process_handshake(false) {}
|
HandshakeState::HandshakeState() : _operation(NULL), _semaphore(1), _thread_in_process_handshake(false) {
|
||||||
|
DEBUG_ONLY(_vmthread_processing_handshake = false;)
|
||||||
|
}
|
||||||
|
|
||||||
void HandshakeState::set_operation(JavaThread* target, HandshakeOperation* op) {
|
void HandshakeState::set_operation(JavaThread* target, HandshakeOperation* op) {
|
||||||
_operation = op;
|
_operation = op;
|
||||||
|
@ -347,10 +337,7 @@ bool HandshakeState::vmthread_can_process_handshake(JavaThread* target) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool possibly_vmthread_can_process_handshake(JavaThread* target) {
|
static bool possibly_vmthread_can_process_handshake(JavaThread* target) {
|
||||||
// An externally suspended thread cannot be resumed while the
|
|
||||||
// Threads_lock is held so it is safe.
|
|
||||||
// Note that this method is allowed to produce false positives.
|
// Note that this method is allowed to produce false positives.
|
||||||
assert(Threads_lock->owned_by_self(), "Not holding Threads_lock.");
|
|
||||||
if (target->is_ext_suspended()) {
|
if (target->is_ext_suspended()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -383,8 +370,6 @@ bool HandshakeState::claim_handshake_for_vmthread() {
|
||||||
|
|
||||||
bool HandshakeState::try_process_by_vmThread(JavaThread* target) {
|
bool HandshakeState::try_process_by_vmThread(JavaThread* target) {
|
||||||
assert(Thread::current()->is_VM_thread(), "should call from vm thread");
|
assert(Thread::current()->is_VM_thread(), "should call from vm thread");
|
||||||
// Threads_lock must be held here, but that is assert()ed in
|
|
||||||
// possibly_vmthread_can_process_handshake().
|
|
||||||
|
|
||||||
if (!has_operation()) {
|
if (!has_operation()) {
|
||||||
// JT has already cleared its handshake
|
// JT has already cleared its handshake
|
||||||
|
@ -408,7 +393,9 @@ bool HandshakeState::try_process_by_vmThread(JavaThread* target) {
|
||||||
if (vmthread_can_process_handshake(target)) {
|
if (vmthread_can_process_handshake(target)) {
|
||||||
guarantee(!_semaphore.trywait(), "we should already own the semaphore");
|
guarantee(!_semaphore.trywait(), "we should already own the semaphore");
|
||||||
log_trace(handshake)("Processing handshake by VMThtread");
|
log_trace(handshake)("Processing handshake by VMThtread");
|
||||||
|
DEBUG_ONLY(_vmthread_processing_handshake = true;)
|
||||||
_operation->do_handshake(target);
|
_operation->do_handshake(target);
|
||||||
|
DEBUG_ONLY(_vmthread_processing_handshake = false;)
|
||||||
// Disarm after VM thread have executed the operation.
|
// Disarm after VM thread have executed the operation.
|
||||||
clear_handshake(target);
|
clear_handshake(target);
|
||||||
executed = true;
|
executed = true;
|
||||||
|
|
|
@ -89,6 +89,12 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool try_process_by_vmThread(JavaThread* target);
|
bool try_process_by_vmThread(JavaThread* target);
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
bool _vmthread_processing_handshake;
|
||||||
|
bool is_vmthread_processing_handshake() const { return _vmthread_processing_handshake; }
|
||||||
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SHARE_RUNTIME_HANDSHAKE_HPP
|
#endif // SHARE_RUNTIME_HANDSHAKE_HPP
|
||||||
|
|
|
@ -187,6 +187,11 @@ void assert_lock_strong(const Mutex* lock) {
|
||||||
if (lock->owned_by_self()) return;
|
if (lock->owned_by_self()) return;
|
||||||
fatal("must own lock %s", lock->name());
|
fatal("must own lock %s", lock->name());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void assert_locked_or_safepoint_or_handshake(const Mutex* lock, const JavaThread* thread) {
|
||||||
|
if (Thread::current()->is_VM_thread() && thread->is_vmthread_processing_handshake()) return;
|
||||||
|
assert_locked_or_safepoint(lock);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define def(var, type, pri, vm_block, safepoint_check_allowed ) { \
|
#define def(var, type, pri, vm_block, safepoint_check_allowed ) { \
|
||||||
|
|
|
@ -174,15 +174,17 @@ void print_owned_locks_on_error(outputStream* st);
|
||||||
|
|
||||||
char *lock_name(Mutex *mutex);
|
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 / handshake)
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
void assert_locked_or_safepoint(const Mutex* lock);
|
void assert_locked_or_safepoint(const Mutex* lock);
|
||||||
void assert_locked_or_safepoint_weak(const Mutex* lock);
|
void assert_locked_or_safepoint_weak(const Mutex* lock);
|
||||||
void assert_lock_strong(const Mutex* lock);
|
void assert_lock_strong(const Mutex* lock);
|
||||||
|
void assert_locked_or_safepoint_or_handshake(const Mutex* lock, const JavaThread* thread);
|
||||||
#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)
|
||||||
#define assert_lock_strong(lock)
|
#define assert_lock_strong(lock)
|
||||||
|
#define assert_locked_or_safepoint_or_handshake(lock, thread)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class MutexLocker: public StackObj {
|
class MutexLocker: public StackObj {
|
||||||
|
|
|
@ -736,10 +736,7 @@ static bool safepoint_safe_with(JavaThread *thread, JavaThreadState state) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SafepointSynchronize::handshake_safe(JavaThread *thread) {
|
bool SafepointSynchronize::handshake_safe(JavaThread *thread) {
|
||||||
// This function must be called with the Threads_lock held so an externally
|
assert(Thread::current()->is_VM_thread(), "Must be VMThread");
|
||||||
// suspended thread cannot be resumed thus it is safe.
|
|
||||||
assert(Threads_lock->owned_by_self() && Thread::current()->is_VM_thread(),
|
|
||||||
"Must hold Threads_lock and be VMThread");
|
|
||||||
if (thread->is_ext_suspended() || thread->is_terminated()) {
|
if (thread->is_ext_suspended() || thread->is_terminated()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3156,7 +3156,7 @@ const char* JavaThread::get_thread_name() const {
|
||||||
if (!(cur->is_Java_thread() && cur == this)) {
|
if (!(cur->is_Java_thread() && cur == this)) {
|
||||||
// Current JavaThreads are allowed to get their own name without
|
// Current JavaThreads are allowed to get their own name without
|
||||||
// the Threads_lock.
|
// the Threads_lock.
|
||||||
assert_locked_or_safepoint(Threads_lock);
|
assert_locked_or_safepoint_or_handshake(Threads_lock, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // ASSERT
|
#endif // ASSERT
|
||||||
|
|
|
@ -1333,6 +1333,12 @@ class JavaThread: public Thread {
|
||||||
return _handshake.try_process_by_vmThread(this);
|
return _handshake.try_process_by_vmThread(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
bool is_vmthread_processing_handshake() const {
|
||||||
|
return _handshake.is_vmthread_processing_handshake();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Suspend/resume support for JavaThread
|
// Suspend/resume support for JavaThread
|
||||||
private:
|
private:
|
||||||
inline void set_ext_suspended();
|
inline void set_ext_suspended();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue