mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-26 05:18:05 +00:00
8305670: Performance regression in LockSupport.unpark with lots of idle threads
Co-authored-by: Robbin Ehn <rehn@openjdk.org> Reviewed-by: rehn, dholmes
This commit is contained in:
parent
ceca198ef2
commit
f030937a51
@ -783,21 +783,22 @@ UNSAFE_ENTRY(void, Unsafe_Park(JNIEnv *env, jobject unsafe, jboolean isAbsolute,
|
||||
|
||||
UNSAFE_ENTRY(void, Unsafe_Unpark(JNIEnv *env, jobject unsafe, jobject jthread)) {
|
||||
if (jthread != nullptr) {
|
||||
ThreadsListHandle tlh;
|
||||
JavaThread* thr = nullptr;
|
||||
oop java_thread = nullptr;
|
||||
(void) tlh.cv_internal_thread_to_JavaThread(jthread, &thr, &java_thread);
|
||||
if (java_thread != nullptr) {
|
||||
// This is a valid oop.
|
||||
if (thr != nullptr) {
|
||||
// The JavaThread is alive.
|
||||
Parker* p = thr->parker();
|
||||
HOTSPOT_THREAD_UNPARK((uintptr_t) p);
|
||||
p->unpark();
|
||||
}
|
||||
oop thread_oop = JNIHandles::resolve_non_null(jthread);
|
||||
// Get the JavaThread* stored in the java.lang.Thread object _before_
|
||||
// the embedded ThreadsListHandle is constructed so we know if the
|
||||
// early life stage of the JavaThread* is protected. We use acquire
|
||||
// here to ensure that if we see a non-nullptr value, then we also
|
||||
// see the main ThreadsList updates from the JavaThread* being added.
|
||||
FastThreadsListHandle ftlh(thread_oop, java_lang_Thread::thread_acquire(thread_oop));
|
||||
JavaThread* thr = ftlh.protected_java_thread();
|
||||
if (thr != nullptr) {
|
||||
// The still live JavaThread* is protected by the FastThreadsListHandle
|
||||
// so it is safe to access.
|
||||
Parker* p = thr->parker();
|
||||
HOTSPOT_THREAD_UNPARK((uintptr_t) p);
|
||||
p->unpark();
|
||||
}
|
||||
} // ThreadsListHandle is destroyed here.
|
||||
|
||||
} // FastThreadsListHandle is destroyed here.
|
||||
} UNSAFE_END
|
||||
|
||||
UNSAFE_ENTRY(jint, Unsafe_GetLoadAverage0(JNIEnv *env, jobject unsafe, jdoubleArray loadavg, jint nelem)) {
|
||||
|
||||
@ -839,6 +839,20 @@ bool ThreadsListHandle::cv_internal_thread_to_JavaThread(jobject jthread,
|
||||
return true;
|
||||
}
|
||||
|
||||
FastThreadsListHandle::FastThreadsListHandle(oop thread_oop, JavaThread* java_thread) : _protected_java_thread(nullptr) {
|
||||
assert(thread_oop != nullptr, "must be");
|
||||
if (java_thread != nullptr) {
|
||||
// We captured a non-nullptr JavaThread* before the _tlh was created
|
||||
// so that covers the early life stage of the target JavaThread.
|
||||
_protected_java_thread = java_lang_Thread::thread(thread_oop);
|
||||
assert(_protected_java_thread == nullptr || _tlh.includes(_protected_java_thread), "must be");
|
||||
// If we captured a non-nullptr JavaThread* after the _tlh was created
|
||||
// then that covers the end life stage of the target JavaThread and we
|
||||
// we know that _tlh protects the JavaThread*. The underlying atomic
|
||||
// load is sufficient (no acquire necessary here).
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadsSMRSupport::add_thread(JavaThread *thread){
|
||||
ThreadsList *new_list = ThreadsList::add_thread(get_java_thread_list(), thread);
|
||||
if (EnableThreadSMRStatistics) {
|
||||
|
||||
@ -333,6 +333,29 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
// This stack allocated FastThreadsListHandle implements the special case
|
||||
// where we want to quickly determine if a JavaThread* is protected by the
|
||||
// embedded ThreadsListHandle.
|
||||
//
|
||||
class FastThreadsListHandle : public StackObj {
|
||||
JavaThread* _protected_java_thread;
|
||||
ThreadsListHandle _tlh;
|
||||
|
||||
public:
|
||||
// The 'java_thread' parameter to the constructor must be provided
|
||||
// by a java_lang_Thread::thread_acquire(thread_oop) call which gets
|
||||
// us the JavaThread* stored in the java.lang.Thread object _before_
|
||||
// the embedded ThreadsListHandle is constructed. We use acquire there
|
||||
// to ensure that if we see a non-nullptr value, then we also see the
|
||||
// main ThreadsList updates from the JavaThread* being added.
|
||||
//
|
||||
FastThreadsListHandle(oop thread_oop, JavaThread* java_thread);
|
||||
|
||||
JavaThread* protected_java_thread() {
|
||||
return _protected_java_thread;
|
||||
}
|
||||
};
|
||||
|
||||
// This stack allocated JavaThreadIterator is used to walk the
|
||||
// specified ThreadsList using the following style:
|
||||
//
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user