JDK-8241403 : JavaThread::get_thread_name() should be ThreadSMR-aware
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 15
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2020-03-23
  • Updated: 2021-11-09
  • Resolved: 2021-02-26
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 17
17 b12Fixed
Related Reports
Relates :  
Relates :  
Description
JavaThread::get_thread_name() requires that the caller own the Threads_lock if not operating on the current thread, to ensure the safety of the access. But since ThreadSMR the use of the Threads_lock is not the primary mechanism for ensuring safe access to a JavaThread. The code should be updated to allow access when the target thread is on a ThreadsList held by the current thread.

Erik O. writes:

There currently is no "can_access_safely()" function. Implementing it is not impossible. The safety is ensured often with hazard pointers,
but in nested cases, there could be some reference counting going on. Fortunately, we have an abstraction called SafeThreadsListPtr, which
abstracts away those details, and importantly, also describe the current nesting in a walkable linked list.

The "top" SafeThreadsListPtr is reachable from Thread::current()->_threads_list_ptr. You can walk the nestings by following the _previous
pointers. By walking these things and checking of the target thread is in any of the ThreadsList instances they point at, you can provide
an accurate answer to "can_access_safely()", in the sane scenarios where it is Thread::current() that ensures the safety.

However, it is worth mentioning that we have some rare cases where the safety is provided through a surrogate thread, so it might look
like it is not safe, when it fact it is. This is very rare though, and unless the assert triggers on that (I hope not), then I think we
should ignore that.

---

Dan D. writes:

This is a way to see if the current thread an associated ThreadsList:

inline ThreadsList* Thread::get_threads_hazard_ptr() {
  return (ThreadsList*)Atomic::load_acquire(&_threads_hazard_ptr);
}

Once you have the ThreadsList, you can use

    ThreadsList::includes(const JavaThread * const p)

to see if your target is on _that_ ThreadsList. If there are nested
ThreadsLists, then more work is required.

Because you are asking the question of your own ThreadsList, I don't
think you need to go through the SafeThreadsListPtr layer and can
deal directly with your own ThreadsList (and probably its nested
ThreadsLists).

Or perhaps the right solution is to add a ThreadsListHandle to this
code and then query the ThreadsListHandle to see if it includes the
target thread (more about this below)... Although that will only
answer the question for the current snapshot and won't answer the
question for any nested ThreadsListHandles that the calling thread
might have...

---

It is noted that until JDK-8240588 is fixed access to the threadObj() would not be truly safe.
Comments
Changeset: 47a08426 Author: Daniel D. Daugherty <dcubed@openjdk.org> Date: 2021-02-26 15:41:13 +0000 URL: https://git.openjdk.java.net/jdk/commit/47a08426
26-02-2021

I'm adding a new function: bool Thread::is_JavaThread_protected(const JavaThread* p) that returns true when the target JavaThread* is protected and false otherwise. Since it's the Thread that contains a chain with the Thread's current ThreadsList and nested ThreadsLists (if any), that seems like the right place to land this new function. JavaThread::get_thread_name() will be updated to create a ThreadsListHandle and will call Thread::current()->is_JavaThread_protected(this) to know whether it is safe to call JavaThread::get_thread_name_string(). There's also a JvmtiTrace::safe_get_thread_name() that could benefit from using Thread::is_JavaThread_protected() and the already existing JavaThread::get_thread_name_string(). I looked through all the callers of JavaThread::get_thread_name() and only one set of calls in one source file needed to have Threads_lock grabs removed.
09-02-2021

The right solution here is to use a local ThreadsListHandle in JavaThread::get_thread_name() when the target thread is not the current JavaThread. If the target thread is not protected by the local ThreadsListHandle, then it is not safe to query that target thread because any other ThreadsListHandle that might be protecting that JavaThread is under the control of some other thread and could go away at any time. When I'm talking about a local ThreadsListHandle I mean the one that we allocate in JavaThread::get_thread_name() and any other nested ThreadsListHandles that are associated with the calling thread.
08-02-2021