1616#include " jvmThread.h"
1717#include " libraries.h"
1818#include " log.h"
19+ #include " mutex.h"
1920#include " os.h"
2021#include " profiler.h"
2122#include " safeAccess.h"
@@ -55,6 +56,12 @@ bool VM::_monitor_events_delegated = false;
5556bool VM ::_native_monitor_events_available = false ;
5657bool VM ::_is_adaptive_gc_boundary_flag_set = false ;
5758
59+ // Serializes the one-time bridge installation and ownership negotiation.
60+ // Callback readers need no synchronization because ownership is assigned
61+ // before callbacks can be enabled and is never changed afterward.
62+ static Mutex profiler_bridge_init_lock;
63+ static bool profiler_bridge_initialized = false ;
64+
5865jvmtiExtensionFunction VM ::_request_stack_trace = nullptr ;
5966jvmtiExtensionFunction VM ::_init_request_stack_trace = nullptr ;
6067
@@ -86,7 +93,7 @@ static void monitorBlockEnter(jvmtiEnv *jvmti, JNIEnv *jni, jthread thread,
8693 !JVMSupport::isPlatformThread (jni, thread)) {
8794 return ;
8895 }
89- ProfiledThread *current = ProfiledThread::current ();
96+ ProfiledThread *current = ProfiledThread::initCurrentThreadSignalSafe ();
9097 if (current == nullptr ) return ;
9198 Context context = ContextApi::snapshot ();
9299 if (context.spanId != 0 ) {
@@ -101,10 +108,15 @@ static void monitorBlockEnter(jvmtiEnv *jvmti, JNIEnv *jni, jthread thread,
101108 bool current_owner = false ;
102109 if (token != 0 ) {
103110 ThreadFilter::SlotID slot_id = ThreadFilter::tokenSlotId (token);
104- BlockRunSnapshot snapshot = tf->snapshotBlockedRun (slot_id);
105- current_owner = current->filterSlotId () == slot_id && snapshot.active &&
106- snapshot.owner == BlockRunOwner::JVMTI &&
107- snapshot.generation == ThreadFilter::tokenGeneration (token);
111+ ThreadFilter::Slot *slot = current->filterSlotId () == slot_id
112+ ? tf->activeSlotForId (slot_id, current->tid ())
113+ : nullptr ;
114+ if (slot != nullptr ) {
115+ BlockRunSnapshot snapshot = slot->snapshotBlockRun ();
116+ current_owner = snapshot.active &&
117+ snapshot.owner == BlockRunOwner::JVMTI &&
118+ snapshot.generation == ThreadFilter::tokenGeneration (token);
119+ }
108120 }
109121 if (current_owner) {
110122 return ;
@@ -117,12 +129,8 @@ static void monitorBlockEnter(jvmtiEnv *jvmti, JNIEnv *jni, jthread thread,
117129 }
118130
119131 ThreadFilter *tf = profiler->threadFilter ();
120- ThreadFilter::SlotID slot_id = current->filterSlotId ();
121- if (slot_id < 0 ) {
122- slot_id = tf->slotIdByTid (current->tid ());
123- if (slot_id >= 0 ) current->setFilterSlotId (slot_id);
124- }
125- if (!tf->allThreads () || slot_id < 0 ) {
132+ ThreadFilter::SlotID slot_id = tf->ensureCurrentThreadSlot (current);
133+ if (!tf->unfilteredWallTrackingActive () || slot_id < 0 ) {
126134 current->clearMonitorBlock ();
127135 return ;
128136 }
@@ -154,31 +162,8 @@ static void monitorBlockExit(JNIEnv *jni, jthread thread, OSThreadState state) {
154162 }
155163
156164 Profiler *profiler = Profiler::instance ();
157- bool recording_enabled = profiler->taskBlockEnabled ();
158- bool activity = profiler->tryEnterTaskBlockActivity ();
159- if (!activity) profiler->waitForTaskBlockRotation ();
160-
161- ThreadFilter *tf = profiler->threadFilter ();
162- ThreadFilter::SlotID slot_id = ThreadFilter::tokenSlotId (token);
163- ThreadFilter::SlotID current_slot = current->filterSlotId ();
164- if (current_slot < 0 ) current_slot = tf->slotIdByTid (current->tid ());
165- BlockRunSnapshot snapshot{};
166- bool exited = current_slot == slot_id &&
167- tf->snapshotAndExitBlockedRun (
168- slot_id, ThreadFilter::tokenGeneration (token), &snapshot);
169-
170- if (!activity) {
171- Counters::increment (TASK_BLOCK_DROPPED_ROTATION );
172- return ;
173- }
174- if (recording_enabled && exited && snapshot.context_eligible ) {
175- recordTaskBlockIfEligible (current->tid (), thread, 0 , start_ticks,
176- TSC::ticks (), context, blocker, 0 ,
177- snapshot.active_state , true );
178- } else if (recording_enabled && exited && !snapshot.context_eligible ) {
179- Counters::increment (TASK_BLOCK_SKIPPED_TRACE_CONTEXT );
180- }
181- profiler->leaveTaskBlockActivity ();
165+ finishTaskBlockAtExit (current, profiler->threadFilter (), thread, 0 , token,
166+ start_ticks, context, blocker, 0 );
182167}
183168
184169static void JNICALL MonitorContendedEnter (jvmtiEnv *jvmti, JNIEnv *jni,
@@ -576,16 +561,25 @@ bool VM::initializeRequestStackTrace() {
576561 return false ;
577562}
578563
579- bool VM::initProfilerBridge (JavaVM *vm, bool attach,
580- bool delegateMonitorEvents) {
564+ ProfilerBridgeInitResult VM::initProfilerBridge (JavaVM *vm, bool attach,
565+ bool delegateMonitorEvents) {
566+ MutexLocker init_locker (profiler_bridge_init_lock);
567+ if (profiler_bridge_initialized) {
568+ bool requested_delegation =
569+ delegateMonitorEvents && _native_monitor_events_available;
570+ return requested_delegation == _monitor_events_delegated
571+ ? ProfilerBridgeInitResult::SUCCESS
572+ : ProfilerBridgeInitResult::MONITOR_EVENTS_DELEGATION_CONFLICT ;
573+ }
574+
581575 TEST_LOG (" VM::initProfilerBridge" );
582576 if (!initShared (vm)) {
583- return false ;
577+ return ProfilerBridgeInitResult:: FAILURE ;
584578 }
585579
586580 CodeCache *lib = openJvmLibrary ();
587581 if (lib == nullptr ) {
588- return false ;
582+ return ProfilerBridgeInitResult:: FAILURE ;
589583 }
590584
591585 if (!attach && hotspot_version () == 8 && OS::isLinux ()) {
@@ -708,7 +702,8 @@ bool VM::initProfilerBridge(JavaVM *vm, bool attach,
708702
709703 OS::installSignalHandler (WAKEUP_SIGNAL , NULL , wakeupHandler);
710704
711- return true ;
705+ profiler_bridge_initialized = true ;
706+ return ProfilerBridgeInitResult::SUCCESS ;
712707}
713708
714709bool VM::setNativeMonitorEventsEnabled (bool enabled) {
@@ -859,7 +854,8 @@ Agent_OnLoad(JavaVM* vm, char* options, void* reserved) {
859854 return ARGUMENTS_ERROR ;
860855 }
861856
862- if (!VM::initProfilerBridge (vm, false )) {
857+ if (VM::initProfilerBridge (vm, false ) !=
858+ ProfilerBridgeInitResult::SUCCESS ) {
863859 Log::error (" JVM does not support Tool Interface" );
864860 return COMMAND_ERROR ;
865861 }
0 commit comments