Skip to content

Commit 6b6242e

Browse files
authored
Merge pull request eclipse-openj9#20885 from adpopescu/jfr-threadpark
Adding in jfr thread park event.
2 parents 3d7fea2 + 1daf74d commit 6b6242e

9 files changed

+219
-5
lines changed

runtime/oti/j9consts.h

+1
Original file line numberDiff line numberDiff line change
@@ -952,6 +952,7 @@ extern "C" {
952952
#define J9JFR_EVENT_TYPE_THREAD_CPU_LOAD 6
953953
#define J9JFR_EVENT_TYPE_CLASS_LOADING_STATISTICS 7
954954
#define J9JFR_EVENT_TYPE_THREAD_CONTEXT_SWITCH_RATE 8
955+
#define J9JFR_EVENT_TYPE_THREAD_PARK 9
955956

956957
/* JFR thread states */
957958

runtime/oti/j9nonbuilder.h

+13
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,19 @@ typedef struct J9JFRMonitorWaited {
421421

422422
#define J9JFRMonitorWaitedED_STACKTRACE(jfrEvent) ((UDATA*)(((J9JFRMonitorWaited*)(jfrEvent)) + 1))
423423

424+
typedef struct J9JFRThreadParked {
425+
J9JFR_EVENT_WITH_STACKTRACE_FIELDS
426+
I_64 time;
427+
I_64 duration;
428+
struct J9VMThread *thread;
429+
struct J9Class *parkedClass;
430+
I_64 timeOut;
431+
I_64 untilTime;
432+
UDATA parkedAddress;
433+
} J9JFRThreadParked;
434+
435+
#define J9JFRTHREADPARKED_STACKTRACE(jfrEvent) ((UDATA*)(((J9JFRThreadParked*)(jfrEvent)) + 1))
436+
424437
typedef struct J9JFRCPULoad {
425438
J9JFR_EVENT_COMMON_FIELDS
426439
float jvmUser;

runtime/oti/j9vm.hdf

+5
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,11 @@ typedef UDATA (* lookupNativeAddressCallback)(struct J9VMThread *currentThread,
604604
</description>
605605
<struct>J9VMUnparkedEvent</struct>
606606
<data type="struct J9VMThread *" name="currentThread" description="current thread" />
607+
<data type="I_64" name="millis" description="milliseconds to park for" />
608+
<data type="IDATA" name="nanos" description="nanoseconds to park for" />
609+
<data type="I_64" name="startTicks" description="current ticks when wait began" />
610+
<data type="UDATA" name="parkedAddress" description="object parked address" />
611+
<data type="struct J9Class*" name="parkedClass" description="the class which park was called from?" />
607612
</event>
608613

609614
<event>

runtime/oti/vm_api.h

+4
Original file line numberDiff line numberDiff line change
@@ -4935,6 +4935,10 @@ void
49354935
threadParkImpl(J9VMThread *vmThread, BOOLEAN timeoutIsEpochRelative, I_64 timeout);
49364936
void
49374937
threadUnparkImpl (J9VMThread* vmThread, j9object_t threadObject);
4938+
J9Class*
4939+
getThreadParkClassObject(J9VMThread *vmThread);
4940+
UDATA
4941+
getThreadParkClassIterator(J9VMThread *vmThread, J9StackWalkState *walkState);
49384942

49394943
/* -------------------- threadhelp.cpp ------------ */
49404944

runtime/vm/JFRChunkWriter.hpp

+46
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ enum MetadataTypeID {
6565
ThreadStartID = 2,
6666
ThreadEndID = 3,
6767
ThreadSleepID = 4,
68+
ThreadParkID = 5,
6869
MonitorWaitID = 7,
6970
JVMInformationID = 87,
7071
OSInformationID = 88,
@@ -339,6 +340,8 @@ class VM_JFRChunkWriter {
339340

340341
pool_do(_constantPoolTypes.getMonitorWaitTable(), &writeMonitorWaitEvent, _bufferWriter);
341342

343+
pool_do(_constantPoolTypes.getThreadParkTable(), &writeThreadParkEvent, _bufferWriter);
344+
342345
pool_do(_constantPoolTypes.getCPULoadTable(), &writeCPULoadEvent, _bufferWriter);
343346

344347
pool_do(_constantPoolTypes.getThreadCPULoadTable(), &writeThreadCPULoadEvent, _bufferWriter);
@@ -552,6 +555,49 @@ class VM_JFRChunkWriter {
552555
_bufferWriter->writeLEB128PaddedU32(dataStart, _bufferWriter->getCursor() - dataStart);
553556
}
554557

558+
static void
559+
writeThreadParkEvent(void *anElement, void *userData)
560+
{
561+
ThreadParkEntry *entry = (ThreadParkEntry *)anElement;
562+
VM_BufferWriter *_bufferWriter = (VM_BufferWriter *) userData;
563+
564+
/* reserve size field */
565+
U_8 *dataStart = _bufferWriter->getAndIncCursor(sizeof(U_32));
566+
567+
/* write event type */
568+
_bufferWriter->writeLEB128(ThreadParkID);
569+
570+
/* write start time - this is when the sleep started not when it ended so we
571+
* need to subtract the duration since the event is emitted when the sleep ends.
572+
*/
573+
_bufferWriter->writeLEB128(entry->ticks - entry->duration);
574+
575+
/* write duration time which is always in ticks, in our case nanos */
576+
_bufferWriter->writeLEB128(entry->duration);
577+
578+
/* write event thread index */
579+
_bufferWriter->writeLEB128(entry->eventThreadIndex);
580+
581+
/* stacktrace index */
582+
_bufferWriter->writeLEB128(entry->stackTraceIndex);
583+
584+
/* class index */
585+
_bufferWriter->writeLEB128(entry->parkedClass);
586+
587+
/* timeout value which is always in millis */
588+
_bufferWriter->writeLEB128(entry->timeOut/1000000);
589+
590+
/* until value which is always in millis */
591+
_bufferWriter->writeLEB128(entry->untilTime/1000000);
592+
593+
/* address of monitor */
594+
_bufferWriter->writeLEB128(entry->parkedAddress);
595+
596+
/* write size */
597+
_bufferWriter->writeLEB128PaddedU32(dataStart, _bufferWriter->getCursor() - dataStart);
598+
}
599+
600+
555601
static void
556602
writeCPULoadEvent(void *anElement, void *userData)
557603
{

runtime/vm/JFRConstantPoolTypes.cpp

+38-4
Original file line numberDiff line numberDiff line change
@@ -1051,8 +1051,8 @@ VM_JFRConstantPoolTypes::addThreadSleepEntry(J9JFRThreadSlept *threadSleepData)
10511051
entry->stackTraceIndex = consumeStackTrace(threadSleepData->vmThread, J9JFRTHREADSLEPT_STACKTRACE(threadSleepData), threadSleepData->stackTraceSize);
10521052
if (isResultNotOKay()) goto done;
10531053

1054-
index = _threadEndCount;
1055-
_threadEndCount += 1;
1054+
index = _threadSleepCount;
1055+
_threadSleepCount += 1;
10561056

10571057
done:
10581058
return index;
@@ -1089,13 +1089,47 @@ VM_JFRConstantPoolTypes::addMonitorWaitEntry(J9JFRMonitorWaited* threadWaitData)
10891089

10901090
entry->notifierThread = 0; //Need a way to find the notifiying thread
10911091

1092-
index = _threadEndCount;
1093-
_threadEndCount += 1;
1092+
index = _monitorWaitCount;
1093+
_monitorWaitCount += 1;
10941094

10951095
done:
10961096
return index;
10971097
}
10981098

1099+
void
1100+
VM_JFRConstantPoolTypes::addThreadParkEntry(J9JFRThreadParked* threadParkData)
1101+
{
1102+
ThreadParkEntry *entry = (ThreadParkEntry*)pool_newElement(_threadParkTable);
1103+
1104+
if (NULL == entry) {
1105+
_buildResult = OutOfMemory;
1106+
goto done;
1107+
}
1108+
1109+
entry->ticks = threadParkData->startTicks;
1110+
entry->duration = threadParkData->duration;
1111+
1112+
entry->parkedAddress = (U_64)threadParkData->parkedAddress;
1113+
1114+
entry->threadIndex = addThreadEntry(threadParkData->vmThread);
1115+
if (isResultNotOKay()) goto done;
1116+
1117+
entry->eventThreadIndex = addThreadEntry(threadParkData->vmThread);
1118+
if (isResultNotOKay()) goto done;
1119+
1120+
entry->stackTraceIndex = consumeStackTrace(threadParkData->vmThread, J9JFRTHREADPARKED_STACKTRACE(threadParkData), threadParkData->stackTraceSize);
1121+
if (isResultNotOKay()) goto done;
1122+
1123+
entry->parkedClass = getClassEntry(threadParkData->parkedClass);
1124+
if (isResultNotOKay()) goto done;
1125+
1126+
entry->timeOut = threadParkData->timeOut;
1127+
entry->untilTime = threadParkData->untilTime;
1128+
1129+
done:
1130+
return;
1131+
}
1132+
10991133
U_32
11001134
VM_JFRConstantPoolTypes::addCPULoadEntry(J9JFRCPULoad *cpuLoadData)
11011135
{

runtime/vm/JFRConstantPoolTypes.hpp

+38
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,18 @@ struct MonitorWaitEntry {
204204
BOOLEAN timedOut;
205205
};
206206

207+
struct ThreadParkEntry {
208+
I_64 ticks;
209+
I_64 duration;
210+
U_32 threadIndex;
211+
U_32 eventThreadIndex;
212+
U_32 stackTraceIndex;
213+
U_32 parkedClass;
214+
I_64 timeOut;
215+
I_64 untilTime;
216+
U_64 parkedAddress;
217+
};
218+
207219
struct StackTraceEntry {
208220
J9VMThread *vmThread;
209221
I_64 ticks;
@@ -316,6 +328,8 @@ class VM_JFRConstantPoolTypes {
316328
UDATA _threadSleepCount;
317329
J9Pool *_monitorWaitTable;
318330
UDATA _monitorWaitCount;
331+
J9Pool *_threadParkTable;
332+
UDATA _threadParkCount;
319333
J9Pool *_cpuLoadTable;
320334
UDATA _cpuLoadCount;
321335
J9Pool *_threadCPULoadTable;
@@ -587,6 +601,8 @@ class VM_JFRConstantPoolTypes {
587601

588602
U_32 addMonitorWaitEntry(J9JFRMonitorWaited* threadWaitData);
589603

604+
void addThreadParkEntry(J9JFRThreadParked* threadParkData);
605+
590606
U_32 addCPULoadEntry(J9JFRCPULoad *cpuLoadData);
591607

592608
U_32 addThreadCPULoadEntry(J9JFRThreadCPULoad *threadCPULoadData);
@@ -620,6 +636,11 @@ class VM_JFRConstantPoolTypes {
620636
return _monitorWaitTable;
621637
}
622638

639+
J9Pool *getThreadParkTable()
640+
{
641+
return _threadParkTable;
642+
}
643+
623644
J9Pool *getCPULoadTable()
624645
{
625646
return _cpuLoadTable;
@@ -665,6 +686,11 @@ class VM_JFRConstantPoolTypes {
665686
return _monitorWaitCount;
666687
}
667688

689+
UDATA getThreadParkCount()
690+
{
691+
return _threadParkCount;
692+
}
693+
668694
UDATA getCPULoadCount()
669695
{
670696
return _cpuLoadCount;
@@ -828,6 +854,9 @@ class VM_JFRConstantPoolTypes {
828854
case J9JFR_EVENT_TYPE_OBJECT_WAIT:
829855
addMonitorWaitEntry((J9JFRMonitorWaited*) event);
830856
break;
857+
case J9JFR_EVENT_TYPE_THREAD_PARK:
858+
addThreadParkEntry((J9JFRThreadParked*) event);
859+
break;
831860
case J9JFR_EVENT_TYPE_CPU_LOAD:
832861
addCPULoadEntry((J9JFRCPULoad *)event);
833862
break;
@@ -1162,6 +1191,8 @@ class VM_JFRConstantPoolTypes {
11621191
, _threadSleepCount(0)
11631192
, _monitorWaitTable(NULL)
11641193
, _monitorWaitCount(0)
1194+
, _threadParkTable(NULL)
1195+
, _threadParkCount(0)
11651196
, _cpuLoadTable(NULL)
11661197
, _cpuLoadCount(0)
11671198
, _threadCPULoadTable(NULL)
@@ -1272,6 +1303,12 @@ class VM_JFRConstantPoolTypes {
12721303
goto done;
12731304
}
12741305

1306+
_threadParkTable = pool_new(sizeof(ThreadParkEntry), 0, sizeof(U_64), 0, J9_GET_CALLSITE(), OMRMEM_CATEGORY_VM, POOL_FOR_PORT(privatePortLibrary));
1307+
if (NULL == _threadParkTable) {
1308+
_buildResult = OutOfMemory;
1309+
goto done;
1310+
}
1311+
12751312
_cpuLoadTable = pool_new(sizeof(CPULoadEntry), 0, sizeof(U_64), 0, J9_GET_CALLSITE(), OMRMEM_CATEGORY_VM, POOL_FOR_PORT(privatePortLibrary));
12761313
if (NULL == _cpuLoadTable) {
12771314
_buildResult = OutOfMemory;
@@ -1382,6 +1419,7 @@ class VM_JFRConstantPoolTypes {
13821419
pool_kill(_threadEndTable);
13831420
pool_kill(_threadSleepTable);
13841421
pool_kill(_monitorWaitTable);
1422+
pool_kill(_threadParkTable);
13851423
pool_kill(_cpuLoadTable);
13861424
pool_kill(_threadCPULoadTable);
13871425
pool_kill(_classLoadingStatisticsTable);

runtime/vm/jfr.cpp

+39
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ static void jfrThreadStarting(J9HookInterface **hook, UDATA eventNum, void *even
5353
static void jfrThreadEnd(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData);
5454
static void jfrVMInitialized(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData);
5555
static void jfrVMMonitorWaited(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData);
56+
static void jfrVMThreadParked(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData);
5657
static void jfrStartSamplingThread(J9JavaVM *vm);
5758
static void initializeEventFields(J9VMThread *currentThread, J9JFREvent *jfrEvent, UDATA eventType);
5859
static int J9THREAD_PROC jfrSamplingThreadProc(void *entryArg);
@@ -87,6 +88,9 @@ jfrEventSize(J9JFREvent *jfrEvent)
8788
case J9JFR_EVENT_TYPE_OBJECT_WAIT:
8889
size = sizeof(J9JFRMonitorWaited) + (((J9JFRMonitorWaited*)jfrEvent)->stackTraceSize * sizeof(UDATA));
8990
break;
91+
case J9JFR_EVENT_TYPE_THREAD_PARK:
92+
size = sizeof(J9JFRThreadParked) + (((J9JFRThreadParked*)jfrEvent)->stackTraceSize * sizeof(UDATA));
93+
break;
9094
case J9JFR_EVENT_TYPE_CPU_LOAD:
9195
size = sizeof(J9JFRCPULoad);
9296
break;
@@ -638,6 +642,36 @@ jfrVMMonitorWaited(J9HookInterface **hook, UDATA eventNum, void *eventData, void
638642
}
639643
}
640644

645+
/**
646+
* Hook for VM thread parked. Called without VM access.
647+
*
648+
* @param hook[in] the VM hook interface
649+
* @param eventNum[in] the event number
650+
* @param eventData[in] the event data
651+
* @param userData[in] the registered user data
652+
*/
653+
static void
654+
jfrVMThreadParked(J9HookInterface **hook, UDATA eventNum, void *eventData, void* userData)
655+
{
656+
J9VMUnparkedEvent *event = (J9VMUnparkedEvent *)eventData;
657+
J9VMThread *currentThread = event->currentThread;
658+
PORT_ACCESS_FROM_VMC(currentThread);
659+
660+
#if defined(DEBUG)
661+
j9tty_printf(PORTLIB, "\n!!! thread park %p\n", currentThread);
662+
#endif /* defined(DEBUG) */
663+
664+
J9JFRThreadParked *jfrEvent = (J9JFRThreadParked*)reserveBufferWithStackTrace(currentThread, currentThread, J9JFR_EVENT_TYPE_THREAD_PARK, sizeof(*jfrEvent));
665+
if (NULL != jfrEvent) {
666+
// TODO: worry about overflow?
667+
jfrEvent->time = (event->millis * 1000000) + event->nanos;
668+
jfrEvent->duration = j9time_nano_time() - event->startTicks;
669+
jfrEvent->parkedAddress = event->parkedAddress;
670+
jfrEvent->parkedClass = event->parkedClass;
671+
}
672+
}
673+
674+
641675
jint
642676
initializeJFR(J9JavaVM *vm, BOOLEAN lateInit)
643677
{
@@ -691,6 +725,10 @@ initializeJFR(J9JavaVM *vm, BOOLEAN lateInit)
691725
goto fail;
692726
}
693727

728+
if ((*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_UNPARKED, jfrVMThreadParked, OMR_GET_CALLSITE(), NULL)) {
729+
goto fail;
730+
}
731+
694732
/* Allocate constantEvents. */
695733
vm->jfrState.constantEvents = j9mem_allocate_memory(sizeof(JFRConstantEvents), J9MEM_CATEGORY_VM);
696734
if (NULL == vm->jfrState.constantEvents) {
@@ -821,6 +859,7 @@ tearDownJFR(J9JavaVM *vm)
821859
/* Unregister it anyway even it wasn't registered for initializeJFR(vm, TRUE). */
822860
(*vmHooks)->J9HookUnregister(vmHooks, J9HOOK_VM_INITIALIZED, jfrVMInitialized, NULL);
823861
(*vmHooks)->J9HookUnregister(vmHooks, J9HOOK_VM_MONITOR_WAITED, jfrVMMonitorWaited, NULL);
862+
(*vmHooks)->J9HookUnregister(vmHooks, J9HOOK_VM_UNPARKED, jfrVMThreadParked, NULL);
824863

825864
/* Free global data */
826865
VM_JFRConstantPoolTypes::freeJFRConstantEvents(vm);

0 commit comments

Comments
 (0)