Skip to content

Commit 3435ace

Browse files
authored
Merge pull request #20903 from adpopescu/jfr-threadpark
(0.49) Adding in JFR threadpark event into release.
2 parents 0568735 + 8a3601c commit 3435ace

File tree

9 files changed

+219
-5
lines changed

9 files changed

+219
-5
lines changed

runtime/oti/j9consts.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -946,6 +946,7 @@ extern "C" {
946946
#define J9JFR_EVENT_TYPE_CPU_LOAD 5
947947
#define J9JFR_EVENT_TYPE_THREAD_CPU_LOAD 6
948948
#define J9JFR_EVENT_TYPE_CLASS_LOADING_STATISTICS 7
949+
#define J9JFR_EVENT_TYPE_THREAD_PARK 9
949950

950951
/* JFR thread states */
951952

runtime/oti/j9nonbuilder.h

Lines changed: 13 additions & 0 deletions
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

Lines changed: 5 additions & 0 deletions
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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4948,6 +4948,10 @@ void
49484948
threadParkImpl(J9VMThread *vmThread, BOOLEAN timeoutIsEpochRelative, I_64 timeout);
49494949
void
49504950
threadUnparkImpl (J9VMThread* vmThread, j9object_t threadObject);
4951+
J9Class*
4952+
getThreadParkClassObject(J9VMThread *vmThread);
4953+
UDATA
4954+
getThreadParkClassIterator(J9VMThread *vmThread, J9StackWalkState *walkState);
49514955

49524956
/* -------------------- threadhelp.cpp ------------ */
49534957

runtime/vm/JFRChunkWriter.hpp

Lines changed: 46 additions & 0 deletions
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,
@@ -337,6 +338,8 @@ class VM_JFRChunkWriter {
337338

338339
pool_do(_constantPoolTypes.getMonitorWaitTable(), &writeMonitorWaitEvent, _bufferWriter);
339340

341+
pool_do(_constantPoolTypes.getThreadParkTable(), &writeThreadParkEvent, _bufferWriter);
342+
340343
pool_do(_constantPoolTypes.getCPULoadTable(), &writeCPULoadEvent, _bufferWriter);
341344

342345
pool_do(_constantPoolTypes.getThreadCPULoadTable(), &writeThreadCPULoadEvent, _bufferWriter);
@@ -548,6 +551,49 @@ class VM_JFRChunkWriter {
548551
_bufferWriter->writeLEB128PaddedU32(dataStart, _bufferWriter->getCursor() - dataStart);
549552
}
550553

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

runtime/vm/JFRConstantPoolTypes.cpp

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1050,8 +1050,8 @@ VM_JFRConstantPoolTypes::addThreadSleepEntry(J9JFRThreadSlept *threadSleepData)
10501050
entry->stackTraceIndex = consumeStackTrace(threadSleepData->vmThread, J9JFRTHREADSLEPT_STACKTRACE(threadSleepData), threadSleepData->stackTraceSize);
10511051
if (isResultNotOKay()) goto done;
10521052

1053-
index = _threadEndCount;
1054-
_threadEndCount += 1;
1053+
index = _threadSleepCount;
1054+
_threadSleepCount += 1;
10551055

10561056
done:
10571057
return index;
@@ -1088,13 +1088,47 @@ VM_JFRConstantPoolTypes::addMonitorWaitEntry(J9JFRMonitorWaited* threadWaitData)
10881088

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

1091-
index = _threadEndCount;
1092-
_threadEndCount += 1;
1091+
index = _monitorWaitCount;
1092+
_monitorWaitCount += 1;
10931093

10941094
done:
10951095
return index;
10961096
}
10971097

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

runtime/vm/JFRConstantPoolTypes.hpp

Lines changed: 38 additions & 0 deletions
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;
@@ -311,6 +323,8 @@ class VM_JFRConstantPoolTypes {
311323
UDATA _threadSleepCount;
312324
J9Pool *_monitorWaitTable;
313325
UDATA _monitorWaitCount;
326+
J9Pool *_threadParkTable;
327+
UDATA _threadParkCount;
314328
J9Pool *_cpuLoadTable;
315329
UDATA _cpuLoadCount;
316330
J9Pool *_threadCPULoadTable;
@@ -580,6 +594,8 @@ class VM_JFRConstantPoolTypes {
580594

581595
U_32 addMonitorWaitEntry(J9JFRMonitorWaited* threadWaitData);
582596

597+
void addThreadParkEntry(J9JFRThreadParked* threadParkData);
598+
583599
U_32 addCPULoadEntry(J9JFRCPULoad *cpuLoadData);
584600

585601
U_32 addThreadCPULoadEntry(J9JFRThreadCPULoad *threadCPULoadData);
@@ -611,6 +627,11 @@ class VM_JFRConstantPoolTypes {
611627
return _monitorWaitTable;
612628
}
613629

630+
J9Pool *getThreadParkTable()
631+
{
632+
return _threadParkTable;
633+
}
634+
614635
J9Pool *getCPULoadTable()
615636
{
616637
return _cpuLoadTable;
@@ -651,6 +672,11 @@ class VM_JFRConstantPoolTypes {
651672
return _monitorWaitCount;
652673
}
653674

675+
UDATA getThreadParkCount()
676+
{
677+
return _threadParkCount;
678+
}
679+
654680
UDATA getCPULoadCount()
655681
{
656682
return _cpuLoadCount;
@@ -809,6 +835,9 @@ class VM_JFRConstantPoolTypes {
809835
case J9JFR_EVENT_TYPE_OBJECT_WAIT:
810836
addMonitorWaitEntry((J9JFRMonitorWaited*) event);
811837
break;
838+
case J9JFR_EVENT_TYPE_THREAD_PARK:
839+
addThreadParkEntry((J9JFRThreadParked*) event);
840+
break;
812841
case J9JFR_EVENT_TYPE_CPU_LOAD:
813842
addCPULoadEntry((J9JFRCPULoad *)event);
814843
break;
@@ -1140,6 +1169,8 @@ class VM_JFRConstantPoolTypes {
11401169
, _threadSleepCount(0)
11411170
, _monitorWaitTable(NULL)
11421171
, _monitorWaitCount(0)
1172+
, _threadParkTable(NULL)
1173+
, _threadParkCount(0)
11431174
, _cpuLoadTable(NULL)
11441175
, _cpuLoadCount(0)
11451176
, _threadCPULoadTable(NULL)
@@ -1248,6 +1279,12 @@ class VM_JFRConstantPoolTypes {
12481279
goto done;
12491280
}
12501281

1282+
_threadParkTable = pool_new(sizeof(ThreadParkEntry), 0, sizeof(U_64), 0, J9_GET_CALLSITE(), OMRMEM_CATEGORY_VM, POOL_FOR_PORT(privatePortLibrary));
1283+
if (NULL == _threadParkTable) {
1284+
_buildResult = OutOfMemory;
1285+
goto done;
1286+
}
1287+
12511288
_cpuLoadTable = pool_new(sizeof(CPULoadEntry), 0, sizeof(U_64), 0, J9_GET_CALLSITE(), OMRMEM_CATEGORY_VM, POOL_FOR_PORT(privatePortLibrary));
12521289
if (NULL == _cpuLoadTable) {
12531290
_buildResult = OutOfMemory;
@@ -1352,6 +1389,7 @@ class VM_JFRConstantPoolTypes {
13521389
pool_kill(_threadEndTable);
13531390
pool_kill(_threadSleepTable);
13541391
pool_kill(_monitorWaitTable);
1392+
pool_kill(_threadParkTable);
13551393
pool_kill(_cpuLoadTable);
13561394
pool_kill(_threadCPULoadTable);
13571395
pool_kill(_classLoadingStatisticsTable);

runtime/vm/jfr.cpp

Lines changed: 39 additions & 0 deletions
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;
@@ -635,6 +639,36 @@ jfrVMMonitorWaited(J9HookInterface **hook, UDATA eventNum, void *eventData, void
635639
}
636640
}
637641

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

724+
if ((*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_UNPARKED, jfrVMThreadParked, OMR_GET_CALLSITE(), NULL)) {
725+
goto fail;
726+
}
727+
690728
/* Allocate constantEvents. */
691729
vm->jfrState.constantEvents = j9mem_allocate_memory(sizeof(JFRConstantEvents), J9MEM_CATEGORY_VM);
692730
if (NULL == vm->jfrState.constantEvents) {
@@ -809,6 +847,7 @@ tearDownJFR(J9JavaVM *vm)
809847
/* Unregister it anyway even it wasn't registered for initializeJFR(vm, TRUE). */
810848
(*vmHooks)->J9HookUnregister(vmHooks, J9HOOK_VM_INITIALIZED, jfrVMInitialized, NULL);
811849
(*vmHooks)->J9HookUnregister(vmHooks, J9HOOK_VM_MONITOR_WAITED, jfrVMMonitorWaited, NULL);
850+
(*vmHooks)->J9HookUnregister(vmHooks, J9HOOK_VM_UNPARKED, jfrVMThreadParked, NULL);
812851

813852
/* Free global data */
814853
VM_JFRConstantPoolTypes::freeJFRConstantEvents(vm);

0 commit comments

Comments
 (0)