Skip to content

Commit 5995786

Browse files
author
Markus Grönlund
committed
8343177: JFR: Remove critical section for thread id assignment
Reviewed-by: dholmes
1 parent 751a914 commit 5995786

File tree

10 files changed

+66
-33
lines changed

10 files changed

+66
-33
lines changed

src/hotspot/share/jfr/jfr.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -100,6 +100,10 @@ void Jfr::on_set_current_thread(JavaThread* jt, oop thread) {
100100
JfrThreadLocal::on_set_current_thread(jt, thread);
101101
}
102102

103+
void Jfr::initialize_main_thread(JavaThread* jt) {
104+
JfrThreadLocal::initialize_main_thread(jt);
105+
}
106+
103107
void Jfr::on_resolution(const CallInfo& info, TRAPS) {
104108
JfrResolution::on_runtime_resolution(info, THREAD);
105109
}

src/hotspot/share/jfr/jfr.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -71,6 +71,7 @@ class Jfr : AllStatic {
7171
static bool on_flight_recorder_option(const JavaVMOption** option, char* delimiter);
7272
static bool on_start_flight_recording_option(const JavaVMOption** option, char* delimiter);
7373
static void on_backpatching(const Method* callee_method, JavaThread* jt);
74+
static void initialize_main_thread(JavaThread* jt);
7475
};
7576

7677
#endif // SHARE_JFR_JFR_HPP

src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ void JfrCheckpointThreadClosure::do_thread(Thread* t) {
114114

115115
void JfrThreadConstantSet::serialize(JfrCheckpointWriter& writer) {
116116
JfrCheckpointThreadClosure tc(writer);
117-
JfrJavaThreadIterator javathreads(false); // include not yet live threads (_thread_new)
117+
JfrJavaThreadIterator javathreads;
118118
while (javathreads.has_next()) {
119119
tc.do_thread(javathreads.next());
120120
}

src/hotspot/share/jfr/recorder/jfrRecorder.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ bool JfrRecorder::on_create_vm_2() {
210210
return true;
211211
}
212212
JavaThread* const thread = JavaThread::current();
213-
JfrThreadLocal::assign_thread_id(thread, thread->jfr_thread_local());
213+
assert(JfrThreadLocal::jvm_thread_id(thread) != 0, "invariant");
214214

215215
if (!JfrOptionSet::initialize(thread)) {
216216
return false;

src/hotspot/share/jfr/support/jfrThreadLocal.cpp

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -71,7 +71,6 @@ JfrThreadLocal::JfrThreadLocal() :
7171
_wallclock_time(os::javaTimeNanos()),
7272
_stackdepth(0),
7373
_entering_suspend_flag(0),
74-
_critical_section(0),
7574
_vthread_epoch(0),
7675
_vthread_excluded(false),
7776
_jvm_thread_excluded(false),
@@ -100,6 +99,14 @@ const JfrBlobHandle& JfrThreadLocal::thread_blob() const {
10099
return _thread;
101100
}
102101

102+
void JfrThreadLocal::initialize_main_thread(JavaThread* jt) {
103+
assert(jt != nullptr, "invariant");
104+
assert(Thread::is_starting_thread(jt), "invariant");
105+
assert(jt->threadObj() == nullptr, "invariant");
106+
assert(jt->jfr_thread_local()->_jvm_thread_id == 0, "invariant");
107+
jt->jfr_thread_local()->_jvm_thread_id = 1;
108+
}
109+
103110
static void send_java_thread_start_event(JavaThread* jt) {
104111
assert(jt != nullptr, "invariant");
105112
assert(Thread::current() == jt, "invariant");
@@ -394,13 +401,13 @@ traceid JfrThreadLocal::thread_id(const Thread* t) {
394401
if (is_impersonating(t)) {
395402
return t->jfr_thread_local()->_thread_id_alias;
396403
}
397-
JfrThreadLocal* const tl = t->jfr_thread_local();
404+
const JfrThreadLocal* const tl = t->jfr_thread_local();
398405
if (!t->is_Java_thread()) {
399-
return jvm_thread_id(t, tl);
406+
return jvm_thread_id(tl);
400407
}
401408
const JavaThread* jt = JavaThread::cast(t);
402409
if (!is_vthread(jt)) {
403-
return jvm_thread_id(t, tl);
410+
return jvm_thread_id(tl);
404411
}
405412
// virtual thread
406413
const traceid tid = vthread_id(jt);
@@ -421,19 +428,30 @@ traceid JfrThreadLocal::external_thread_id(const Thread* t) {
421428
return JfrRecorder::is_recording() ? thread_id(t) : jvm_thread_id(t);
422429
}
423430

424-
inline traceid load_java_thread_id(const Thread* t) {
431+
static inline traceid load_java_thread_id(const Thread* t) {
425432
assert(t != nullptr, "invariant");
426433
assert(t->is_Java_thread(), "invariant");
427434
oop threadObj = JavaThread::cast(t)->threadObj();
428435
return threadObj != nullptr ? AccessThreadTraceId::id(threadObj) : 0;
429436
}
430437

438+
#ifdef ASSERT
439+
static bool can_assign(const Thread* t) {
440+
assert(t != nullptr, "invariant");
441+
if (!t->is_Java_thread()) {
442+
return true;
443+
}
444+
const JavaThread* jt = JavaThread::cast(t);
445+
return jt->thread_state() == _thread_new || jt->is_attaching_via_jni();
446+
}
447+
#endif
448+
431449
traceid JfrThreadLocal::assign_thread_id(const Thread* t, JfrThreadLocal* tl) {
432450
assert(t != nullptr, "invariant");
433451
assert(tl != nullptr, "invariant");
434-
JfrSpinlockHelper spinlock(&tl->_critical_section);
435452
traceid tid = tl->_jvm_thread_id;
436453
if (tid == 0) {
454+
assert(can_assign(t), "invariant");
437455
if (t->is_Java_thread()) {
438456
tid = load_java_thread_id(t);
439457
tl->_jvm_thread_id = tid;
@@ -446,15 +464,14 @@ traceid JfrThreadLocal::assign_thread_id(const Thread* t, JfrThreadLocal* tl) {
446464
return tid;
447465
}
448466

449-
traceid JfrThreadLocal::jvm_thread_id(const Thread* t, JfrThreadLocal* tl) {
450-
assert(t != nullptr, "invariant");
467+
traceid JfrThreadLocal::jvm_thread_id(const JfrThreadLocal* tl) {
451468
assert(tl != nullptr, "invariant");
452-
return tl->_jvm_thread_id != 0 ? tl->_jvm_thread_id : JfrThreadLocal::assign_thread_id(t, tl);
469+
return tl->_jvm_thread_id;
453470
}
454471

455472
traceid JfrThreadLocal::jvm_thread_id(const Thread* t) {
456473
assert(t != nullptr, "invariant");
457-
return jvm_thread_id(t, t->jfr_thread_local());
474+
return jvm_thread_id(t->jfr_thread_local());
458475
}
459476

460477
bool JfrThreadLocal::is_vthread(const JavaThread* jt) {

src/hotspot/share/jfr/support/jfrThreadLocal.hpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -38,7 +38,6 @@ class JfrThreadLocal {
3838
friend class Jfr;
3939
friend class JfrIntrinsicSupport;
4040
friend class JfrJavaSupport;
41-
friend class JfrRecorder;
4241
friend class JVMCIVMStructs;
4342
private:
4443
jobject _java_event_writer;
@@ -65,7 +64,6 @@ class JfrThreadLocal {
6564
jlong _wallclock_time;
6665
mutable u4 _stackdepth;
6766
volatile jint _entering_suspend_flag;
68-
mutable volatile int _critical_section;
6967
u2 _vthread_epoch;
7068
bool _vthread_excluded;
7169
bool _jvm_thread_excluded;
@@ -78,11 +76,13 @@ class JfrThreadLocal {
7876
JfrStackFrame* install_stackframes() const;
7977
void release(Thread* t);
8078
static void release(JfrThreadLocal* tl, Thread* t);
79+
static void initialize_main_thread(JavaThread* jt);
8180

8281
static void set(bool* excluded_field, bool state);
8382
static traceid assign_thread_id(const Thread* t, JfrThreadLocal* tl);
8483
static traceid vthread_id(const Thread* t);
8584
static void set_vthread_epoch(const JavaThread* jt, traceid id, u2 epoch);
85+
static traceid jvm_thread_id(const JfrThreadLocal* tl);
8686
bool is_vthread_excluded() const;
8787
static void exclude_vthread(const JavaThread* jt);
8888
static void include_vthread(const JavaThread* jt);
@@ -175,7 +175,6 @@ class JfrThreadLocal {
175175

176176
// Non-volatile thread id, for Java carrier threads and non-java threads.
177177
static traceid jvm_thread_id(const Thread* t);
178-
static traceid jvm_thread_id(const Thread* t, JfrThreadLocal* tl);
179178

180179
// To impersonate is to temporarily masquerade as another thread.
181180
// For example, when writing an event that should be attributed to some other thread.

src/hotspot/share/prims/jni.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3849,6 +3849,9 @@ static jint attach_current_thread(JavaVM *vm, void **penv, void *_args, bool dae
38493849
return JNI_ERR;
38503850
}
38513851

3852+
// Want this inside 'attaching via jni'.
3853+
JFR_ONLY(Jfr::on_thread_start(thread);)
3854+
38523855
// mark the thread as no longer attaching
38533856
// this uses a fence to push the change through so we don't have
38543857
// to regrab the threads_lock
@@ -3863,8 +3866,6 @@ static jint attach_current_thread(JavaVM *vm, void **penv, void *_args, bool dae
38633866
JvmtiExport::post_thread_start(thread);
38643867
}
38653868

3866-
JFR_ONLY(Jfr::on_thread_start(thread);)
3867-
38683869
*(JNIEnv**)penv = thread->jni_environment();
38693870

38703871
// Now leaving the VM, so change thread_state. This is normally automatically taken care

src/hotspot/share/runtime/thread.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,6 @@ THREAD_LOCAL Thread* Thread::_thr_current = nullptr;
6262
// Base class for all threads: VMThread, WatcherThread, ConcurrentMarkSweepThread,
6363
// JavaThread
6464

65-
DEBUG_ONLY(Thread* Thread::_starting_thread = nullptr;)
66-
6765
Thread::Thread(MemTag mem_tag) {
6866

6967
DEBUG_ONLY(_run_state = PRE_CALL_RUN;)
@@ -538,14 +536,22 @@ void Thread::print_owned_locks_on(outputStream* st) const {
538536
}
539537
}
540538
}
539+
540+
Thread* Thread::_starting_thread = nullptr;
541+
542+
bool Thread::is_starting_thread(const Thread* t) {
543+
assert(_starting_thread != nullptr, "invariant");
544+
return t == _starting_thread;
545+
}
541546
#endif // ASSERT
542547

543-
bool Thread::set_as_starting_thread() {
548+
bool Thread::set_as_starting_thread(JavaThread* jt) {
549+
assert(jt != nullptr, "invariant");
544550
assert(_starting_thread == nullptr, "already initialized: "
545551
"_starting_thread=" INTPTR_FORMAT, p2i(_starting_thread));
546-
// NOTE: this must be called inside the main thread.
547-
DEBUG_ONLY(_starting_thread = this;)
548-
return os::create_main_thread(JavaThread::cast(this));
552+
// NOTE: this must be called from Threads::create_vm().
553+
DEBUG_ONLY(_starting_thread = jt;)
554+
return os::create_main_thread(jt);
549555
}
550556

551557
// Ad-hoc mutual exclusion primitives: SpinLock

src/hotspot/share/runtime/thread.hpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -163,9 +163,6 @@ class Thread: public ThreadShadow {
163163
// const char* _exception_file; // file information for exception (debugging only)
164164
// int _exception_line; // line information for exception (debugging only)
165165
protected:
166-
167-
DEBUG_ONLY(static Thread* _starting_thread;)
168-
169166
// JavaThread lifecycle support:
170167
friend class SafeThreadsListPtr; // for _threads_list_ptr, cmpxchg_threads_hazard_ptr(), {dec_,inc_,}nested_threads_hazard_ptr_cnt(), {g,s}et_threads_hazard_ptr(), inc_nested_handle_cnt(), tag_hazard_ptr() access
171168
friend class ScanHazardPtrGatherProtectedThreadsClosure; // for cmpxchg_threads_hazard_ptr(), get_threads_hazard_ptr(), is_hazard_ptr_tagged() access
@@ -211,12 +208,15 @@ class Thread: public ThreadShadow {
211208
static bool is_JavaThread_protected_by_TLH(const JavaThread* target);
212209

213210
private:
211+
DEBUG_ONLY(static Thread* _starting_thread;)
214212
DEBUG_ONLY(bool _suspendible_thread;)
215213
DEBUG_ONLY(bool _indirectly_suspendible_thread;)
216214
DEBUG_ONLY(bool _indirectly_safepoint_thread;)
217215

218216
public:
219217
#ifdef ASSERT
218+
static bool is_starting_thread(const Thread* t);
219+
220220
void set_suspendible_thread() { _suspendible_thread = true; }
221221
void clear_suspendible_thread() { _suspendible_thread = false; }
222222
bool is_suspendible_thread() { return _suspendible_thread; }
@@ -500,9 +500,9 @@ class Thread: public ThreadShadow {
500500
return is_in_stack_range_incl(adr, os::current_stack_pointer());
501501
}
502502

503-
// Sets this thread as starting thread. Returns failure if thread
503+
// Sets the argument thread as starting thread. Returns failure if thread
504504
// creation fails due to lack of memory, too many threads etc.
505-
bool set_as_starting_thread();
505+
static bool set_as_starting_thread(JavaThread* jt);
506506

507507
protected:
508508
// OS data associated with the thread

src/hotspot/share/runtime/threads.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,9 @@ static void create_initial_thread(Handle thread_group, JavaThread* thread,
166166
string,
167167
CHECK);
168168

169+
JFR_ONLY(assert(JFR_JVM_THREAD_ID(thread) == static_cast<traceid>(java_lang_Thread::thread_id(thread_oop())),
170+
"initial tid mismatch");)
171+
169172
// Set thread status to running since main thread has
170173
// been started and running.
171174
java_lang_Thread::set_thread_status(thread_oop(),
@@ -532,14 +535,16 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
532535
main_thread->set_active_handles(JNIHandleBlock::allocate_block());
533536
MACOS_AARCH64_ONLY(main_thread->init_wx());
534537

535-
if (!main_thread->set_as_starting_thread()) {
538+
if (!Thread::set_as_starting_thread(main_thread)) {
536539
vm_shutdown_during_initialization(
537540
"Failed necessary internal allocation. Out of swap space");
538541
main_thread->smr_delete();
539542
*canTryAgain = false; // don't let caller call JNI_CreateJavaVM again
540543
return JNI_ENOMEM;
541544
}
542545

546+
JFR_ONLY(Jfr::initialize_main_thread(main_thread);)
547+
543548
// Enable guard page *after* os::create_main_thread(), otherwise it would
544549
// crash Linux VM, see notes in os_linux.cpp.
545550
main_thread->stack_overflow_state()->create_stack_guard_pages();

0 commit comments

Comments
 (0)