From 99ca9c9a775cc84fc1d4a7aeb6436770e1bf1691 Mon Sep 17 00:00:00 2001 From: Tobi Ajila Date: Tue, 12 Nov 2024 11:14:56 -0500 Subject: [PATCH] Fix JFR synchronization issues - Assert that VM access is always held while interacting with JFR buffer - Previously, we stored classhashtable entries. Class hashtable can grow and these entries become stale. Instead use romClass as the key for the package table - Previously, we iterated ClassEntry hashtables while adding entries to them (see fixupShallowEntries), this results in corruption. Instead we now make a list of the classes we need to scan (findShallowEntries), then walk the list and add scan entries after. - Dont create tables with J9HASH_TABLE_ALLOW_SIZE_OPTIMIZATION since we cant use that flag and iterate them. Other fixes: - dont assume moduleName is always non-NULL - skip thread flush if the buffer is NULL - add aserts to non-sensible events Signed-off-by: Tobi Ajila --- runtime/util/cphelp.c | 14 ++++--- runtime/vm/JFRConstantPoolTypes.cpp | 30 ++++++++++----- runtime/vm/JFRConstantPoolTypes.hpp | 45 ++++++++++++++++------ runtime/vm/jfr.cpp | 60 ++++++++++++++++++++++++----- 4 files changed, 111 insertions(+), 38 deletions(-) diff --git a/runtime/util/cphelp.c b/runtime/util/cphelp.c index cbe3bde1d44..9b7c8e85cb8 100644 --- a/runtime/util/cphelp.c +++ b/runtime/util/cphelp.c @@ -67,7 +67,7 @@ getClassLocation(J9VMThread * currentThread, J9Class * clazz, UDATA *length) if (NULL != classLoader->classLocationHashTable) { J9ClassLocation *classLocation = vmFuncs->findClassLocationForClass(currentThread, clazz); - + if (NULL != classLocation) { switch(classLocation->locationType) { case LOAD_LOCATION_PATCH_PATH_NON_GENERATED: @@ -86,7 +86,7 @@ getClassLocation(J9VMThread * currentThread, J9Class * clazz, UDATA *length) case LOAD_LOCATION_CLASSPATH_NON_GENERATED: case LOAD_LOCATION_CLASSPATH: - rc = getClassPathEntry(currentThread, classLoader, classLocation->entryIndex, &entry); + rc = getClassPathEntry(currentThread, classLoader, classLocation->entryIndex, &entry); if (0 == rc) { *length = entry.pathLength; path = entry.path; @@ -149,7 +149,9 @@ getModuleJRTURL(J9VMThread *currentThread, J9ClassLoader *classLoader, J9Module if (NULL == jrtURL) { if (J9_ARE_ALL_BITS_SET(javaVM->runtimeFlags, J9_RUNTIME_JAVA_BASE_MODULE_CREATED)) { /* set jrt URL for the module */ - jrtURL = vmFuncs->copyStringToJ9UTF8WithMemAlloc(currentThread, module->moduleName, J9_STR_NONE, "jrt:/", 5, NULL, 0); + if (NULL != module->moduleName) { + jrtURL = vmFuncs->copyStringToJ9UTF8WithMemAlloc(currentThread, module->moduleName, J9_STR_NONE, "jrt:/", 5, NULL, 0); + } if (NULL == jrtURL) { goto _exit; @@ -162,7 +164,7 @@ getModuleJRTURL(J9VMThread *currentThread, J9ClassLoader *classLoader, J9Module if (NULL == jrtURL) { goto _exit; } - memcpy(J9UTF8_DATA(jrtURL), J9UTF8_DATA(&jrtJavaBaseUrl), length); + memcpy(J9UTF8_DATA(jrtURL), J9UTF8_DATA(&jrtJavaBaseUrl), length); J9UTF8_SET_LENGTH(jrtURL, length); } moduleInfo->jrtURL = jrtURL; @@ -219,9 +221,9 @@ addJarToSystemClassLoaderClassPathEntries(J9JavaVM *vm, const char *filename) #if defined(J9VM_OPT_SHARED_CLASSES) if (J9_ARE_ALL_BITS_SET(classLoader->flags, J9CLASSLOADER_SHARED_CLASSES_ENABLED)) { - /* + /* * Warm up the classpath entry so that the Classpath stored in the cache has the correct info. - * This is required because when we are finding classes in the cache, initializeClassPathEntry is not called + * This is required because when we are finding classes in the cache, initializeClassPathEntry is not called * */ if (vm->internalVMFunctions->initializeClassPathEntry(vm, cpEntry) != CPE_TYPE_JAR) { goto done; diff --git a/runtime/vm/JFRConstantPoolTypes.cpp b/runtime/vm/JFRConstantPoolTypes.cpp index 5d8bf49559a..7079cee0eea 100644 --- a/runtime/vm/JFRConstantPoolTypes.cpp +++ b/runtime/vm/JFRConstantPoolTypes.cpp @@ -50,7 +50,7 @@ VM_JFRConstantPoolTypes::jfrPackageHashFn(void *key, void *userData) { PackageEntry *packageEntry = (PackageEntry *) key; - return *(UDATA*)&packageEntry->pkgID; + return *(UDATA*)&packageEntry->romClass; } UDATA @@ -59,7 +59,7 @@ VM_JFRConstantPoolTypes::jfrPackageHashEqualFn(void *tableNode, void *queryNode, PackageEntry *tableEntry = (PackageEntry *) tableNode; PackageEntry *queryEntry = (PackageEntry *) queryNode; - return tableEntry->pkgID == queryEntry->pkgID; + return tableEntry->romClass == queryEntry->romClass; } UDATA @@ -308,17 +308,28 @@ VM_JFRConstantPoolTypes::walkStackTraceTablePrint(void *entry, void *userData) return FALSE; } + UDATA -VM_JFRConstantPoolTypes::fixupShallowEntries(void *entry, void *userData) +VM_JFRConstantPoolTypes::findShallowEntries(void *entry, void *userData) { ClassEntry *tableEntry = (ClassEntry *) entry; - VM_JFRConstantPoolTypes *cp = (VM_JFRConstantPoolTypes*) userData; + J9Pool *shallowEntries = (J9Pool*) userData; - cp->getClassEntry(tableEntry->clazz); + ClassEntry **newEntry = (ClassEntry**)pool_newElement(shallowEntries); + *newEntry = tableEntry; return FALSE; } +void +VM_JFRConstantPoolTypes::fixupShallowEntries(void *entry, void *userData) +{ + ClassEntry *tableEntry = *(ClassEntry **) entry; + VM_JFRConstantPoolTypes *cp = (VM_JFRConstantPoolTypes*) userData; + + cp->getClassEntry(tableEntry->clazz); +} + UDATA VM_JFRConstantPoolTypes::mergeStringUTF8EntriesToGlobalTable(void *entry, void *userData) { @@ -335,11 +346,9 @@ VM_JFRConstantPoolTypes::mergePackageEntriesToGlobalTable(void *entry, void *use { PackageEntry *tableEntry = (PackageEntry *) entry; VM_JFRConstantPoolTypes *cp = (VM_JFRConstantPoolTypes*) userData; - UDATA packageNameLength = 0; - getPackageName(tableEntry->pkgID, &packageNameLength); cp->_globalStringTable[tableEntry->index + cp->_stringUTF8Count] = tableEntry; - cp->_requiredBufferSize += packageNameLength; + cp->_requiredBufferSize += tableEntry->packageNameLength; return FALSE; } @@ -472,7 +481,8 @@ VM_JFRConstantPoolTypes::addPackageEntry(J9Class *clazz) _buildResult = OK; pkgID = hashPkgTableAt(clazz->classLoader, clazz->romClass); - entry->pkgID = pkgID; + entry->romClass = clazz->romClass; + entry->ramClass = clazz; if (NULL == pkgID) { /* default pacakge */ @@ -491,7 +501,7 @@ VM_JFRConstantPoolTypes::addPackageEntry(J9Class *clazz) entry->moduleIndex = addModuleEntry(clazz->module); if (isResultNotOKay()) goto done; - packageName = (const char *) getPackageName(entry->pkgID, &packageNameLength); + packageName = (const char *) getPackageName(pkgID, &packageNameLength); if (NULL == packageName) { _buildResult = InternalVMError; goto done; diff --git a/runtime/vm/JFRConstantPoolTypes.hpp b/runtime/vm/JFRConstantPoolTypes.hpp index 6693e20aed7..00cc05a44f8 100644 --- a/runtime/vm/JFRConstantPoolTypes.hpp +++ b/runtime/vm/JFRConstantPoolTypes.hpp @@ -87,7 +87,8 @@ struct ClassEntry { }; struct PackageEntry { - J9PackageIDTableEntry *pkgID; + J9ROMClass *romClass; + J9Class *ramClass; U_32 moduleIndex; BOOLEAN exported; U_32 packageNameLength; @@ -406,7 +407,9 @@ class VM_JFRConstantPoolTypes { static UDATA walkStackTraceTablePrint(void *entry, void *userData); - static UDATA fixupShallowEntries(void *entry, void *userData); + static UDATA findShallowEntries(void *entry, void *userData); + + static void fixupShallowEntries(void *anElement, void *userData); static UDATA walkMethodTablePrint(void *entry, void *userData); @@ -750,6 +753,7 @@ class VM_JFRConstantPoolTypes { void loadEvents() { J9JFRBufferWalkState walkstate = {0}; + J9Pool *shallowEntries = NULL; J9JFREvent *event = jfrBufferStartDo(&_vm->jfrBuffer, &walkstate); while (NULL != event) { @@ -782,8 +786,25 @@ class VM_JFRConstantPoolTypes { event = jfrBufferNextDo(&walkstate); } - hashTableForEachDo(_classTable, &fixupShallowEntries, this); + if (isResultNotOKay()) { + goto done; + } + + shallowEntries = pool_new(sizeof(ClassEntry**), 0, sizeof(U_64), 0, J9_GET_CALLSITE(), OMRMEM_CATEGORY_VM, POOL_FOR_PORT(privatePortLibrary)); + if (NULL == shallowEntries) { + _buildResult = OutOfMemory; + goto done; + } + + hashTableForEachDo(_classTable, &findShallowEntries, shallowEntries); + pool_do(shallowEntries, &fixupShallowEntries, this); + + pool_kill(shallowEntries); + mergeStringTables(); + +done: + return; } U_32 consumeStackTrace(J9VMThread *walkThread, UDATA *walkStateCache, UDATA numberOfFrames) { @@ -1099,55 +1120,55 @@ class VM_JFRConstantPoolTypes { , _firstPackageEntry(NULL) , _requiredBufferSize(0) { - _classTable = hashTableNew(OMRPORT_FROM_J9PORT(privatePortLibrary), J9_GET_CALLSITE(), 0, sizeof(ClassEntry), sizeof(ClassEntry *), J9HASH_TABLE_ALLOW_SIZE_OPTIMIZATION, J9MEM_CATEGORY_CLASSES, jfrClassHashFn, jfrClassHashEqualFn, NULL, _vm); + _classTable = hashTableNew(OMRPORT_FROM_J9PORT(privatePortLibrary), J9_GET_CALLSITE(), 0, sizeof(ClassEntry), sizeof(ClassEntry *), 0, J9MEM_CATEGORY_CLASSES, jfrClassHashFn, jfrClassHashEqualFn, NULL, _vm); if (NULL == _classTable) { _buildResult = OutOfMemory; goto done; } - _packageTable = hashTableNew(OMRPORT_FROM_J9PORT(privatePortLibrary), J9_GET_CALLSITE(), 0, sizeof(PackageEntry), sizeof(PackageEntry *), J9HASH_TABLE_ALLOW_SIZE_OPTIMIZATION, J9MEM_CATEGORY_CLASSES, jfrPackageHashFn, jfrPackageHashEqualFn, NULL, _vm); + _packageTable = hashTableNew(OMRPORT_FROM_J9PORT(privatePortLibrary), J9_GET_CALLSITE(), 0, sizeof(PackageEntry), sizeof(PackageEntry *), 0, J9MEM_CATEGORY_CLASSES, jfrPackageHashFn, jfrPackageHashEqualFn, NULL, _vm); if (NULL == _packageTable) { _buildResult = OutOfMemory; goto done; } - _classLoaderTable = hashTableNew(OMRPORT_FROM_J9PORT(privatePortLibrary), J9_GET_CALLSITE(), 0, sizeof(ClassloaderEntry), sizeof(J9ClassLoader*), J9HASH_TABLE_ALLOW_SIZE_OPTIMIZATION, J9MEM_CATEGORY_CLASSES, classloaderNameHashFn, classloaderNameHashEqualFn, NULL, _vm); + _classLoaderTable = hashTableNew(OMRPORT_FROM_J9PORT(privatePortLibrary), J9_GET_CALLSITE(), 0, sizeof(ClassloaderEntry), sizeof(J9ClassLoader*), 0, J9MEM_CATEGORY_CLASSES, classloaderNameHashFn, classloaderNameHashEqualFn, NULL, _vm); if (NULL == _classLoaderTable) { _buildResult = OutOfMemory; goto done; } - _methodTable = hashTableNew(OMRPORT_FROM_J9PORT(privatePortLibrary), J9_GET_CALLSITE(), 0, sizeof(MethodEntry), sizeof(J9ROMMethod*), J9HASH_TABLE_ALLOW_SIZE_OPTIMIZATION, J9MEM_CATEGORY_CLASSES, methodNameHashFn, methodNameHashEqualFn, NULL, _vm); + _methodTable = hashTableNew(OMRPORT_FROM_J9PORT(privatePortLibrary), J9_GET_CALLSITE(), 0, sizeof(MethodEntry), sizeof(J9ROMMethod*), 0, J9MEM_CATEGORY_CLASSES, methodNameHashFn, methodNameHashEqualFn, NULL, _vm); if (NULL == _methodTable) { _buildResult = OutOfMemory; goto done; } - _stringUTF8Table = hashTableNew(OMRPORT_FROM_J9PORT(privatePortLibrary), J9_GET_CALLSITE(), 0, sizeof(StringUTF8Entry), sizeof(StringUTF8Entry*), J9HASH_TABLE_ALLOW_SIZE_OPTIMIZATION, J9MEM_CATEGORY_CLASSES, jfrStringUTF8HashFn, jfrStringUTF8HashEqualFn, NULL, _vm); + _stringUTF8Table = hashTableNew(OMRPORT_FROM_J9PORT(privatePortLibrary), J9_GET_CALLSITE(), 0, sizeof(StringUTF8Entry), sizeof(StringUTF8Entry*), 0, J9MEM_CATEGORY_CLASSES, jfrStringUTF8HashFn, jfrStringUTF8HashEqualFn, NULL, _vm); if (NULL == _stringUTF8Table) { _buildResult = OutOfMemory; goto done; } - _moduleTable = hashTableNew(OMRPORT_FROM_J9PORT(privatePortLibrary), J9_GET_CALLSITE(), 0, sizeof(ModuleEntry), sizeof(ModuleEntry*), J9HASH_TABLE_ALLOW_SIZE_OPTIMIZATION, J9MEM_CATEGORY_CLASSES, jfrModuleHashFn, jfrModuleHashEqualFn, NULL, _vm); + _moduleTable = hashTableNew(OMRPORT_FROM_J9PORT(privatePortLibrary), J9_GET_CALLSITE(), 0, sizeof(ModuleEntry), sizeof(ModuleEntry*), 0, J9MEM_CATEGORY_CLASSES, jfrModuleHashFn, jfrModuleHashEqualFn, NULL, _vm); if (NULL == _moduleTable) { _buildResult = OutOfMemory; goto done; } - _threadTable = hashTableNew(OMRPORT_FROM_J9PORT(privatePortLibrary), J9_GET_CALLSITE(), 0, sizeof(ThreadEntry), sizeof(U_64), J9HASH_TABLE_ALLOW_SIZE_OPTIMIZATION, J9MEM_CATEGORY_CLASSES, threadHashFn, threadHashEqualFn, NULL, _currentThread); + _threadTable = hashTableNew(OMRPORT_FROM_J9PORT(privatePortLibrary), J9_GET_CALLSITE(), 0, sizeof(ThreadEntry), sizeof(U_64), 0, J9MEM_CATEGORY_CLASSES, threadHashFn, threadHashEqualFn, NULL, _currentThread); if (NULL == _threadTable) { _buildResult = OutOfMemory; goto done; } - _stackTraceTable = hashTableNew(OMRPORT_FROM_J9PORT(privatePortLibrary), J9_GET_CALLSITE(), 0, sizeof(StackTraceEntry), sizeof(U_64), J9HASH_TABLE_ALLOW_SIZE_OPTIMIZATION, J9MEM_CATEGORY_CLASSES, stackTraceHashFn, stackTraceHashEqualFn, NULL, _vm); + _stackTraceTable = hashTableNew(OMRPORT_FROM_J9PORT(privatePortLibrary), J9_GET_CALLSITE(), 0, sizeof(StackTraceEntry), sizeof(U_64), 0, J9MEM_CATEGORY_CLASSES, stackTraceHashFn, stackTraceHashEqualFn, NULL, _vm); if (NULL == _stackTraceTable) { _buildResult = OutOfMemory; goto done; } - _threadGroupTable = hashTableNew(OMRPORT_FROM_J9PORT(privatePortLibrary), J9_GET_CALLSITE(), 0, sizeof(ThreadGroupEntry), sizeof(U_64), J9HASH_TABLE_ALLOW_SIZE_OPTIMIZATION, J9MEM_CATEGORY_CLASSES, threadGroupHashFn, threadGroupHashEqualFn, NULL, _vm); + _threadGroupTable = hashTableNew(OMRPORT_FROM_J9PORT(privatePortLibrary), J9_GET_CALLSITE(), 0, sizeof(ThreadGroupEntry), sizeof(U_64), 0, J9MEM_CATEGORY_CLASSES, threadGroupHashFn, threadGroupHashEqualFn, NULL, _vm); if (NULL == _threadGroupTable) { _buildResult = OutOfMemory; goto done; diff --git a/runtime/vm/jfr.cpp b/runtime/vm/jfr.cpp index 6e7f42370ae..5c3a87975f2 100644 --- a/runtime/vm/jfr.cpp +++ b/runtime/vm/jfr.cpp @@ -42,7 +42,7 @@ extern "C" { static UDATA jfrEventSize(J9JFREvent *jfrEvent); static bool flushBufferToGlobal(J9VMThread *currentThread, J9VMThread *flushThread); -static bool flushAllThreadBuffers(J9VMThread *currentThread, bool freeBuffers, bool threadEnd); +static bool flushAllThreadBuffers(J9VMThread *currentThread, bool freeBuffers); static U_8* reserveBuffer(J9VMThread *currentThread, UDATA size); static J9JFREvent* reserveBufferWithStackTrace(J9VMThread *currentThread, J9VMThread *sampleThread, UDATA eventType, UDATA eventFixedSize); static void jfrThreadCreated(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData); @@ -118,11 +118,16 @@ jfrBufferNextDo(J9JFRBufferWalkState *walkState) U_8 *current = walkState->current; U_8 *next = current + jfrEventSize((J9JFREvent*)current); + if (walkState->end < next) { + /* must be corruption */ + Assert_VM_unreachable(); + } + if (walkState->end == next) { next = NULL; } - walkState->current = next; + walkState->current = (U_8*)next; return (J9JFREvent*)next; } @@ -152,6 +157,11 @@ writeOutGlobalBuffer(J9VMThread *currentThread, bool finalWrite) vm->jfrBuffer.bufferRemaining = vm->jfrBuffer.bufferSize; vm->jfrBuffer.bufferCurrent = vm->jfrBuffer.bufferStart; + +#if defined(DEBUG) + memset(vm->jfrBuffer.bufferStart, 0, J9JFR_GLOBAL_BUFFER_SIZE); +#endif /* defined(DEBUG) */ + return true; } @@ -173,6 +183,10 @@ flushBufferToGlobal(J9VMThread *currentThread, J9VMThread *flushThread) UDATA bufferSize = flushThread->jfrBuffer.bufferCurrent - flushThread->jfrBuffer.bufferStart; bool success = true; + if (NULL == flushThread->jfrBuffer.bufferStart) { + goto done; + } + #if defined(DEBUG) PORT_ACCESS_FROM_VMC(currentThread); j9tty_printf(PORTLIB, "\n!!! flushing %p of size %u start=%p current=%p\n", flushThread, (U_32)bufferSize, flushThread->jfrBuffer.bufferStart, flushThread->jfrBuffer.bufferCurrent); @@ -194,6 +208,11 @@ flushBufferToGlobal(J9VMThread *currentThread, J9VMThread *flushThread) /* Reset the buffer */ flushThread->jfrBuffer.bufferRemaining = flushThread->jfrBuffer.bufferSize; flushThread->jfrBuffer.bufferCurrent = flushThread->jfrBuffer.bufferStart; + +#if defined(DEBUG) + memset(flushThread->jfrBuffer.bufferStart, 0, J9JFR_THREAD_BUFFER_SIZE); +#endif /* defined(DEBUG) */ + done: return success; } @@ -209,12 +228,16 @@ flushBufferToGlobal(J9VMThread *currentThread, J9VMThread *flushThread) * @returns true if all buffers flushed successfully, false if not */ static bool -flushAllThreadBuffers(J9VMThread *currentThread, bool freeBuffers, bool threadEnd) +flushAllThreadBuffers(J9VMThread *currentThread, bool freeBuffers) { PORT_ACCESS_FROM_VMC(currentThread); J9JavaVM *vm = currentThread->javaVM; J9VMThread *loopThread = vm->mainThread; bool allSucceeded = true; + bool flushedCurrentThread = false; + + Assert_VM_mustHaveVMAccess(currentThread); + Assert_VM_true((J9_XACCESS_EXCLUSIVE == vm->exclusiveAccessState) || (J9_XACCESS_EXCLUSIVE == vm->safePointState)); do { if (!flushBufferToGlobal(currentThread, loopThread)) { @@ -224,10 +247,15 @@ flushAllThreadBuffers(J9VMThread *currentThread, bool freeBuffers, bool threadEn j9mem_free_memory((void*)loopThread->jfrBuffer.bufferStart); memset(&loopThread->jfrBuffer, 0, sizeof(loopThread->jfrBuffer)); } + + if (loopThread == currentThread) { + flushedCurrentThread = true; + } + loopThread = J9_LINKED_LIST_NEXT_DO(vm->mainThread, loopThread); } while (loopThread != NULL); - if (threadEnd) { + if (!flushedCurrentThread) { /* current thread will not be in thread list */ if (!flushBufferToGlobal(currentThread, currentThread)) { allSucceeded = false; @@ -253,7 +281,7 @@ static U_8* reserveBuffer(J9VMThread *currentThread, UDATA size) { U_8 *jfrEvent = NULL; - + Assert_VM_mustHaveVMAccess(currentThread); /* If the event is larger than the buffer, fail without attemptiong to flush */ if (size <= currentThread->jfrBuffer.bufferSize) { /* If there isn't enough space, flush the thread buffer to global */ @@ -337,6 +365,9 @@ jfrThreadCreated(J9HookInterface **hook, UDATA eventNum, void *eventData, void * currentThread->jfrBuffer.bufferCurrent = buffer; currentThread->jfrBuffer.bufferSize = J9JFR_THREAD_BUFFER_SIZE; currentThread->jfrBuffer.bufferRemaining = J9JFR_THREAD_BUFFER_SIZE; +#if defined(DEBUG) + memset(currentThread->jfrBuffer.bufferStart, 0, J9JFR_THREAD_BUFFER_SIZE); +#endif /* defined(DEBUG) */ } } @@ -363,7 +394,7 @@ jfrThreadDestroy(J9HookInterface **hook, UDATA eventNum, void *eventData, void * /* The current thread pointer (which can appear in other thread buffers) is about to become * invalid, so write out all of the available data now. */ - flushAllThreadBuffers(currentThread, false, true); + flushAllThreadBuffers(currentThread, false); writeOutGlobalBuffer(currentThread, false); /* Free the thread local buffer */ @@ -395,7 +426,7 @@ jfrClassesUnload(J9HookInterface **hook, UDATA eventNum, void *eventData, void * /* Some class pointers in the thread and global buffers are about the become * invalid, so write out all of the available data now. */ - flushAllThreadBuffers(currentThread, false, false); + flushAllThreadBuffers(currentThread, false); writeOutGlobalBuffer(currentThread, false); } @@ -426,7 +457,7 @@ jfrVMShutdown(J9HookInterface **hook, UDATA eventNum, void *eventData, void *use } /* Flush and free all the thread buffers and write out the global buffer */ - flushAllThreadBuffers(currentThread, true, false); + flushAllThreadBuffers(currentThread, true); writeOutGlobalBuffer(currentThread, true); if (acquiredExclusive) { @@ -483,10 +514,12 @@ jfrThreadEnd(J9HookInterface **hook, UDATA eventNum, void *eventData, void *user j9tty_printf(PORTLIB, "\n!!! thread end %p\n", currentThread); #endif /* defined(DEBUG) */ + internalAcquireVMAccess(currentThread); J9JFREvent *jfrEvent = (J9JFREvent*)reserveBuffer(currentThread, sizeof(J9JFREvent)); if (NULL != jfrEvent) { initializeEventFields(currentThread, jfrEvent, J9JFR_EVENT_TYPE_THREAD_END); } + internalReleaseVMAccess(currentThread); } /** @@ -655,6 +688,11 @@ initializeJFR(J9JavaVM *vm, BOOLEAN lateInit) if (NULL == buffer) { goto fail; } + +#if defined(DEBUG) + memset(buffer, 0, J9JFR_GLOBAL_BUFFER_SIZE); +#endif /* defined(DEBUG) */ + vm->jfrBuffer.bufferStart = buffer; vm->jfrBuffer.bufferCurrent = buffer; vm->jfrBuffer.bufferSize = J9JFR_GLOBAL_BUFFER_SIZE; @@ -876,7 +914,7 @@ jfrThreadCPULoad(J9VMThread *currentThread, J9VMThread *sampleThread) intptr_t rc = omrthread_get_thread_times(&threadTimes); if (-1 != rc) { - J9JFRThreadCPULoad *jfrEvent = (J9JFRThreadCPULoad *)reserveBuffer(currentThread, sizeof(*jfrEvent)); + J9JFRThreadCPULoad *jfrEvent = (J9JFRThreadCPULoad *)reserveBuffer(currentThread, sizeof(J9JFRThreadCPULoad)); if (NULL != jfrEvent) { initializeEventFields(currentThread, (J9JFREvent *)jfrEvent, J9JFR_EVENT_TYPE_THREAD_CPU_LOAD); @@ -917,7 +955,9 @@ jfrSamplingThreadProc(void *entryArg) while (J9JFR_SAMPLER_STATE_STOP != vm->jfrSamplerState) { J9SignalAsyncEvent(vm, NULL, vm->jfrAsyncKey); if (0 == (count % 100)) { // 1 second + internalAcquireVMAccess(currentThread); jfrCPULoad(currentThread); + internalReleaseVMAccess(currentThread); if (0 == (count % 1000)) { // 10 seconds J9SignalAsyncEvent(vm, NULL, vm->jfrThreadCPULoadAsyncKey); } @@ -956,7 +996,7 @@ jfrDump(J9VMThread *currentThread, BOOLEAN finalWrite) Assert_VM_true((J9_XACCESS_EXCLUSIVE == vm->exclusiveAccessState) || (J9_XACCESS_EXCLUSIVE == vm->safePointState)); /* Flush all the thread buffers and write out the global buffer. */ - flushAllThreadBuffers(currentThread, finalWrite, false); + flushAllThreadBuffers(currentThread, finalWrite); writeOutGlobalBuffer(currentThread, finalWrite); } } /* extern "C" */