From ced2f455242a2af703dcd9184ac777ab3e55ce58 Mon Sep 17 00:00:00 2001 From: Aleksandar Micic Date: Fri, 1 Mar 2024 12:43:20 -0500 Subject: [PATCH] Introduce Flush Caches For GC hook It will trigger before flushing itself, so that users can report or process stats for various application thread caches before they are cleared. Signed-off-by: Aleksandar Micic --- gc/base/OMRVMInterface.cpp | 36 ++++++++++++++++++++++-------------- gc/include/omrmm.hdf | 13 +++++++++++++ 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/gc/base/OMRVMInterface.cpp b/gc/base/OMRVMInterface.cpp index ac7118a8ac5..9628b26c937 100644 --- a/gc/base/OMRVMInterface.cpp +++ b/gc/base/OMRVMInterface.cpp @@ -46,9 +46,9 @@ extern "C" { * Actions required prior to walking the heap. */ void -hookWalkHeapStart(J9HookInterface** hook, uintptr_t eventNum, void* eventData, void* userData) +hookWalkHeapStart(J9HookInterface **hook, uintptr_t eventNum, void *eventData, void *userData) { - MM_WalkHeapStartEvent* event = (MM_WalkHeapStartEvent*)eventData; + MM_WalkHeapStartEvent *event = (MM_WalkHeapStartEvent *)eventData; GC_OMRVMInterface::flushCachesForWalk(event->omrVM); } @@ -56,7 +56,7 @@ hookWalkHeapStart(J9HookInterface** hook, uintptr_t eventNum, void* eventData, v * Actions required after to walking the heap. */ void -hookWalkHeapEnd(J9HookInterface** hook, uintptr_t eventNum, void* eventData, void* userData) +hookWalkHeapEnd(J9HookInterface** hook, uintptr_t eventNum, void *eventData, void *userData) { /* Nothing to do right now */ } @@ -69,7 +69,7 @@ hookWalkHeapEnd(J9HookInterface** hook, uintptr_t eventNum, void* eventData, voi void GC_OMRVMInterface::initializeExtensions(MM_GCExtensionsBase *extensions) { - J9HookInterface** mmPrivateHooks = J9_HOOK_INTERFACE(extensions->privateHookInterface); + J9HookInterface **mmPrivateHooks = J9_HOOK_INTERFACE(extensions->privateHookInterface); (*mmPrivateHooks)->J9HookRegisterWithCallSite(mmPrivateHooks, J9HOOK_MM_PRIVATE_WALK_HEAP_START, hookWalkHeapStart, OMR_GET_CALLSITE(), NULL); (*mmPrivateHooks)->J9HookRegisterWithCallSite(mmPrivateHooks, J9HOOK_MM_PRIVATE_WALK_HEAP_END, hookWalkHeapEnd, OMR_GET_CALLSITE(), NULL); @@ -88,7 +88,7 @@ GC_OMRVMInterface::getOmrHookInterface(MM_GCExtensionsBase *extensions) * Flush Cache for walk. */ void -GC_OMRVMInterface::flushCachesForWalk(OMR_VM* omrVM) +GC_OMRVMInterface::flushCachesForWalk(OMR_VM *omrVM) { /* * Environment at this point might be fake, so we can not get this thread info @@ -96,11 +96,11 @@ GC_OMRVMInterface::flushCachesForWalk(OMR_VM* omrVM) */ //Assert_MM_true(J9_XACCESS_EXCLUSIVE == vm->exclusiveAccessState); - OMR_VMThread *omrVMThread; + OMR_VMThread *omrVMThread = NULL; GC_OMRVMThreadListIterator threadListIterator(omrVM); - while((omrVMThread = threadListIterator.nextOMRVMThread()) != NULL) { + while ((omrVMThread = threadListIterator.nextOMRVMThread()) != NULL) { MM_EnvironmentBase *envToFlush = MM_EnvironmentBase::getEnvironment(omrVMThread); GC_OMRVMThreadInterface::flushCachesForWalk(envToFlush); } @@ -112,20 +112,28 @@ GC_OMRVMInterface::flushCachesForWalk(OMR_VM* omrVM) void GC_OMRVMInterface::flushCachesForGC(MM_EnvironmentBase *env) { + OMRPORT_ACCESS_FROM_ENVIRONMENT(env); + MM_GCExtensionsBase *extensions = env->getExtensions(); - OMR_VMThread *omrVMThread; + OMR_VMThread *omrVMThread = NULL; UDATA allocatedBytesMax = extensions->bytesAllocatedMost; OMR_VMThread *vmThreadMax = extensions->vmThreadAllocatedMost; + TRIGGER_J9HOOK_MM_OMR_FLUSH_CACHES_FOR_GC( + extensions->omrHookInterface, + env->getOmrVMThread(), + omrtime_hires_clock(), + J9HOOK_MM_OMR_FLUSH_CACHES_FOR_GC); + GC_OMRVMThreadListIterator threadListIterator(env->getOmrVM()); - while((omrVMThread = threadListIterator.nextOMRVMThread()) != NULL) { + while ((omrVMThread = threadListIterator.nextOMRVMThread()) != NULL) { /* Grab allocation bytes stats per-thread before they're cleared */ - MM_EnvironmentBase* threadEnv = MM_EnvironmentBase::getEnvironment(omrVMThread); - MM_AllocationStats * stats= threadEnv->_objectAllocationInterface->getAllocationStats(); + MM_EnvironmentBase *threadEnv = MM_EnvironmentBase::getEnvironment(omrVMThread); + MM_AllocationStats *stats= threadEnv->_objectAllocationInterface->getAllocationStats(); UDATA allocatedBytes = stats->bytesAllocated(); - if(allocatedBytes >= allocatedBytesMax){ + if (allocatedBytes >= allocatedBytesMax){ allocatedBytesMax = allocatedBytes; vmThreadMax = omrVMThread; } @@ -142,11 +150,11 @@ GC_OMRVMInterface::flushCachesForGC(MM_EnvironmentBase *env) void GC_OMRVMInterface::flushNonAllocationCaches(MM_EnvironmentBase *env) { - OMR_VMThread *omrVMThread; + OMR_VMThread *omrVMThread = NULL; GC_OMRVMThreadListIterator threadListIterator(env->getOmrVM()); - while((omrVMThread = threadListIterator.nextOMRVMThread()) != NULL) { + while ((omrVMThread = threadListIterator.nextOMRVMThread()) != NULL) { GC_OMRVMThreadInterface::flushNonAllocationCaches(MM_EnvironmentBase::getEnvironment(omrVMThread)); } } diff --git a/gc/include/omrmm.hdf b/gc/include/omrmm.hdf index d7fed30d4df..6851c4515c2 100644 --- a/gc/include/omrmm.hdf +++ b/gc/include/omrmm.hdf @@ -285,4 +285,17 @@ typedef uintptr_t (*condYieldFromGCFunctionPtr) (OMR_VMThread *omrVMThread, uint + + J9HOOK_MM_OMR_FLUSH_CACHES_FOR_GC + + This is called slightly after exclusive VM access is acquired, and slightly before various GC start hooks. + This is called before flush itself, which deletes all the stats of the various application thread caches. + So, it's very similar to the GC start event, except all the stats are still available for reporting and processing. + + MM_FlushCachesForGCEvent + + + + +