RFR: 8305670: Performance regression in LockSupport.unpark with lots of idle threads [v2]
David Holmes
dholmes at openjdk.org
Thu Apr 20 01:01:55 UTC 2023
On Wed, 19 Apr 2023 17:20:28 GMT, Daniel D. Daugherty <dcubed at openjdk.org> wrote:
>> As a caller of cv_internal_thread_to_JavaThread we do not know the implementation of quick_mode.
>>
>> As the implementation is now, we still want the asserts.
>
> In particular we want this assert from `cv_internal_thread_to_JavaThread()`:
>
> assert(includes(java_thread), "must be");
>
> because that verifies our assumptions from this call-site that `quick_mode` is okay.
>
> Also, it is possible that a JavaThread that's racing to exit will make it past `ensure_join()`
> after our check on L789 above and run into this block in the conversion function:
>
> JavaThread *java_thread = java_lang_Thread::thread(thread_oop);
> if (java_thread == nullptr) {
> // The java.lang.Thread does not contain a JavaThread* so it has not
> // run enough to be put on a ThreadsList or it has exited enough to
> // make it past ensure_join() where the JavaThread* is cleared.
> return false;
> }
>
>
> Because we (the observer thread) captured the target JavaThread in the
> ThreadsListHandle, it's safe for us to use the `JavaThread*`, but I've always
> been a fan of bailing on operations like these as soon as we detect that the
> `JavaThread*` is exiting.
But ignoring the asserts `cv_internal_thread_to_JavaThread()` serves absolutely no purpose when we could request quick-mode - and we don't need to know what `cv_internal_thread_to_JavaThread` does - we know how thread startup and exit is managed and we know what a TLH guarantees . Sure we can bail sooner but there is no need to, so that is not required. In quick-mode, barring the assertion for includes, it all boils down to nothing! We don't need the Thread_oop passed out as we already have it before we start; we don't even need the JavaThread* passed out as we already have it too! So what does it actually do for us? Nothing. We could just have:
UNSAFE_ENTRY(void, Unsafe_Unpark(JNIEnv *env, jobject unsafe, jobject jthread)) {
if (jthread != nullptr) {
oop thread_oop = JNIHandles::resolve_non_null(jthread);
if (java_lang_Thread::thread(thread_oop) != nullptr) {
// Try to capture the live JavaThread in a ThreadsListHandle:
ThreadsListHandle tlh; // Provides memory barrier
JavaThread* thr;
if ( (thr = java_lang_Thread::thread(thread_oop)) != nullptr) {
assert(tlh.includes(thr), "must be");
// The still live JavaThread is protected by the ThreadsListHandle
// so is safe to access.
Parker* p = thr->parker();
HOTSPOT_THREAD_UNPARK((uintptr_t) p);
p->unpark();
}
} // ThreadsListHandle is destroyed here.
}
} UNSAFE_END
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/13519#discussion_r1171978423
More information about the hotspot-runtime-dev
mailing list