8340547: Starting many threads can delay safepoints

Reviewed-by: shade, qamai, dholmes
This commit is contained in:
Oli Gillespie 2024-10-09 15:28:44 +00:00
parent c30ad0124e
commit e704c055a4
5 changed files with 15 additions and 3 deletions

View File

@ -2948,9 +2948,10 @@ JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread))
// We must release the Threads_lock before we can post a jvmti event
// in Thread::start.
{
ConditionalMutexLocker throttle_ml(ThreadsLockThrottle_lock, UseThreadsLockThrottleLock);
// Ensure that the C++ Thread and OSThread structures aren't freed before
// we operate.
MutexLocker mu(Threads_lock);
MutexLocker ml(Threads_lock);
// Since JDK 5 the java.lang.Thread threadStatus is used to prevent
// re-starting an already started thread, so we should usually find

View File

@ -1991,6 +1991,10 @@ const int ObjectAlignmentInBytes = 8;
\
product(bool, StressSecondarySupers, false, DIAGNOSTIC, \
"Use a terrible hash function in order to generate many collisions.") \
\
product(bool, UseThreadsLockThrottleLock, true, DIAGNOSTIC, \
"Use an extra lock during Thread start and exit to alleviate" \
"contention on Threads_lock.") \
// end of RUNTIME_FLAGS

View File

@ -66,6 +66,7 @@ Monitor* CodeCache_lock = nullptr;
Mutex* TouchedMethodLog_lock = nullptr;
Mutex* RetData_lock = nullptr;
Monitor* VMOperation_lock = nullptr;
Monitor* ThreadsLockThrottle_lock = nullptr;
Monitor* Threads_lock = nullptr;
Mutex* NonJavaThreadsList_lock = nullptr;
Mutex* NonJavaThreadsListSync_lock = nullptr;
@ -317,6 +318,8 @@ void mutex_init() {
MUTEX_DEFN(JVMCIRuntime_lock , PaddedMonitor, safepoint, true);
#endif
MUTEX_DEFN(ThreadsLockThrottle_lock , PaddedMonitor, safepoint);
// These locks have relative rankings, and inherit safepoint checking attributes from that rank.
MUTEX_DEFL(VtableStubs_lock , PaddedMutex , CompiledIC_lock); // Also holds DumpTimeTable_lock
MUTEX_DEFL(CodeCache_lock , PaddedMonitor, VtableStubs_lock);

View File

@ -61,6 +61,8 @@ extern Monitor* CodeCache_lock; // a lock on the CodeCache
extern Mutex* TouchedMethodLog_lock; // a lock on allocation of LogExecutedMethods info
extern Mutex* RetData_lock; // a lock on installation of RetData inside method data
extern Monitor* VMOperation_lock; // a lock on queue of vm_operations waiting to execute
extern Monitor* ThreadsLockThrottle_lock; // used by Thread start/exit to reduce competition for Threads_lock,
// so a VM thread calling a safepoint is prioritized
extern Monitor* Threads_lock; // a lock on the Threads table of active Java threads
// (also used by Safepoints too to block threads creation/destruction)
extern Mutex* NonJavaThreadsList_lock; // a lock on the NonJavaThreads list

View File

@ -1028,7 +1028,9 @@ void Threads::add(JavaThread* p, bool force_daemon) {
void Threads::remove(JavaThread* p, bool is_daemon) {
// Extra scope needed for Thread_lock, so we can check
// that we do not remove thread without safepoint code notice
{ MonitorLocker ml(Threads_lock);
{
ConditionalMutexLocker throttle_ml(ThreadsLockThrottle_lock, UseThreadsLockThrottleLock);
MonitorLocker ml(Threads_lock);
if (ThreadIdTable::is_initialized()) {
// This cleanup must be done before the current thread's GC barrier
@ -1076,7 +1078,7 @@ void Threads::remove(JavaThread* p, bool is_daemon) {
// Notify threads waiting in EscapeBarriers
EscapeBarrier::thread_removed(p);
} // unlock Threads_lock
} // unlock Threads_lock and ThreadsLockThrottle_lock
// Reduce the ObjectMonitor ceiling for the exiting thread.
ObjectSynchronizer::dec_in_use_list_ceiling();