Skip to content

Commit 2b9845c

Browse files
committed
Add missing exclusive access for thread iteration
Acquire exclusive when allocating the local JFR buffers so if any new threads are created in this period they must wait for the iteration to complete. After the iteration is complete the thread creation hook is added so new threads will trigger that. Also instead of requesting threadCPU sample on the requestor thread, trigger the async check so threadCPU is captured on all threads. Signed-off-by: Tobi Ajila <atobia@ca.ibm.com>
1 parent 16776fb commit 2b9845c

4 files changed

Lines changed: 47 additions & 1 deletion

File tree

runtime/jcl/common/com_ibm_oti_vm_VM.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,9 @@ Java_com_ibm_oti_vm_VM_startJFR(JNIEnv *env, jclass unused)
262262

263263
if (!vmFuncs->isJFRRecordingStarted(vm)) {
264264
/* this is to initalize JFR late after VM startup */
265+
vmFuncs->internalEnterVMFromJNI(currentThread);
265266
rc = vmFuncs->initializeJFR(vm);
267+
vmFuncs->internalExitVMToJNI(currentThread);
266268
}
267269

268270
return rc;

runtime/jcl/common/jdk_jfr_internal_JVM_common.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,7 @@ Java_jdk_jfr_internal_JVM_createJFR(JNIEnv *env, jobject obj, jboolean simulateF
377377
vmFuncs->internalEnterVMFromJNI(currentThread);
378378
if (JNI_OK != vmFuncs->initializeJFR(vm)) {
379379
rc = JNI_FALSE;
380+
goto done;
380381
}
381382

382383
if (!vm->internalVMFunctions->setupChunkMonitor(currentThread)) {

runtime/vm/jfr.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,9 @@ jfrStartSamplingThread(J9JavaVM *vm)
710710
{
711711
/* Start the sampler thread. */
712712
IDATA rc = omrthread_create(&(vm->jfrSamplerThread), vm->defaultOSStackSize, J9THREAD_PRIORITY_NORMAL, FALSE, jfrSamplingThreadProc, (void *)vm);
713+
714+
Assert_VM_mustNotHaveVMAccess(currentVMThread(vm));
715+
713716
if (0 == rc) {
714717
omrthread_monitor_enter(vm->jfrSamplerMutex);
715718
while (J9JFR_SAMPLER_STATE_UNINITIALIZED == vm->jfrSamplerState) {
@@ -950,9 +953,12 @@ initializeJFR(J9JavaVM *vm)
950953

951954
U_8 *buffer = NULL;
952955
UDATA timeSuccess = 0;
956+
J9VMThread *currentThread = currentVMThread(vm);
953957
J9VMThread *walkThread = NULL;
958+
J9HookInterface **vmHooks = getVMHookInterface(vm);
954959

955960
Assert_VM_false(vm->jfrState.isCreated);
961+
Assert_VM_mustHaveVMAccess(currentThread);
956962

957963
/* Register async handler for execution samples. */
958964
vm->jfrAsyncKey = J9RegisterAsyncEvent(vm, jfrExecutionSampleCallback, NULL);
@@ -1031,6 +1037,7 @@ initializeJFR(J9JavaVM *vm)
10311037
goto fail;
10321038
}
10331039

1040+
acquireExclusiveVMAccess(currentThread);
10341041
/* Go through existing threads. */
10351042
walkThread = J9_LINKED_LIST_START_DO(vm->mainThread);
10361043
while (NULL != walkThread) {
@@ -1050,6 +1057,12 @@ initializeJFR(J9JavaVM *vm)
10501057
walkThread = J9_LINKED_LIST_NEXT_DO(vm->mainThread, walkThread);
10511058
}
10521059

1060+
if ((*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_THREAD_CREATED, jfrThreadCreated, OMR_GET_CALLSITE(), NULL)) {
1061+
goto done;
1062+
}
1063+
1064+
releaseExclusiveVMAccess(currentThread);
1065+
10531066
vm->jfrState.isCreated = TRUE;
10541067

10551068
if (!isJFRV2SupportEnabled(vm)) {
@@ -1072,6 +1085,7 @@ startJFRRecording(J9JavaVM *vm)
10721085
J9HookInterface **vmHooks = getVMHookInterface(vm);
10731086
BOOLEAN rc = FALSE;
10741087

1088+
Assert_VM_mustHaveVMAccess(currentThread);
10751089
Assert_VM_false(vm->jfrState.isStarted);
10761090
Assert_VM_true(vm->jfrState.isCreated);
10771091

@@ -1110,7 +1124,9 @@ startJFRRecording(J9JavaVM *vm)
11101124
goto done;
11111125
}
11121126

1127+
internalReleaseVMAccess(currentThread);
11131128
jfrStartSamplingThread(vm);
1129+
internalAcquireVMAccess(currentThread);
11141130

11151131
vm->jfrState.isStarted = TRUE;
11161132

@@ -2216,7 +2232,8 @@ JfrPeriodicEventSet::requestCPULoad(J9VMThread *currentThread)
22162232
void
22172233
JfrPeriodicEventSet::requestThreadCPULoad(J9VMThread *currentThread)
22182234
{
2219-
jfrThreadCPULoad(currentThread, currentThread);
2235+
J9JavaVM *vm = currentThread->javaVM;
2236+
J9SignalAsyncEvent(vm, NULL, vm->jfrThreadCPULoadAsyncKey);
22202237
}
22212238

22222239
void

test/functional/cmdLineTests/jfr/jfrV2.xml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,4 +107,30 @@ SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-ex
107107
<output type="failure" caseSensitive="yes" regex="no">Found additional fields in mirror class</output>
108108
<output type="failure" caseSensitive="yes" regex="no">Error</output>
109109
</test>
110+
<test id="test jfr summary - approx 5 seconds">
111+
<command>$JFR_EXE$ summary testrecording.jfr</command>
112+
<output type="required" caseSensitive="yes" regex="no">Version: 2.1</output>
113+
<output type="required" caseSensitive="yes" regex="no">jdk.ExecutionSample</output>
114+
<output type="success" caseSensitive="yes" regex="no">jdk.CPULoad</output>
115+
<output type="success" caseSensitive="yes" regex="no">jdk.JavaThreadStatistics</output>
116+
<output type="success" caseSensitive="yes" regex="no">jdk.ClassLoadingStatistics</output>
117+
<output type="success" caseSensitive="yes" regex="no">jdk.ThreadCPULoad</output>
118+
<output type="required" caseSensitive="yes" regex="no">jdk.Metadata</output>
119+
</test>
120+
<test id="test jfr execution sample - approx 5 seconds">
121+
<command>$JFR_EXE$ print --xml --events "ExecutionSample" --stack-depth 1 testrecording.jfr</command>
122+
<output type="required" caseSensitive="yes" regex="no">http://www.w3.org/2001/XMLSchema-instance</output>
123+
<output type="required" caseSensitive="yes" regex="no">jdk.ExecutionSample</output>
124+
<output type="required" caseSensitive="yes" regex="no">startTime</output>
125+
<output type="required" caseSensitive="yes" regex="no">sampledThread</output>
126+
<output type="required" caseSensitive="yes" regex="no">stackTrace</output>
127+
<output type="required" caseSensitive="yes" regex="no">frames</output>
128+
<output type="success" caseSensitive="yes" regex="no">STATE_RUNNABLE</output>
129+
<output type="failure" caseSensitive="yes" regex="no">jfr print: could not read recording</output>
130+
</test>
131+
<test id="Test JFRv2 with profile config">
132+
<command>$EXE$ -XX:+EnableOpenJ9ExperimentalFlightRecording -XX:StartFlightRecording:filename=profile.jfr,dumponexit=true,settings=profile.jfc --add-opens jdk.jfr/jdk.jfr.internal=ALL-UNNAMED -cp $RESJAR$ org.openj9.test.WorkLoad</command>
133+
<output type="success" caseSensitive="yes" regex="no">All runs complete</output>
134+
<output type="required" caseSensitive="yes" regex="no">0 / 100 complete</output>
135+
</test>
110136
</suite>

0 commit comments

Comments
 (0)