/** * Verify port library management. * * The port library allocates resources as part of it's normal running. Thus * prior to terminating the application the port library must free all it's * resource via the port library table function * @ref omrport.c::omrport_shutdown_library "omrport_shutdown_library()" * * @note self allocated port libraries de-allocate their memory as part of this * function. */ TEST(PortTest, port_test6) { OMRPORT_ACCESS_FROM_OMRPORT(portTestEnv->getPortLibrary()); const char *testName = "omrport_test6"; OMRPortLibrary *fakePtr; int32_t rc; omrthread_t attachedThread = NULL; reportTestEntry(OMRPORTLIB, testName); if (0 != omrthread_attach_ex(&attachedThread, J9THREAD_ATTR_DEFAULT)) { outputErrorMessage(PORTTEST_ERROR_ARGS, "Failed to attach to omrthread\n"); goto exit; } memset(&portLibraryToTest, '0', sizeof(OMRPortLibrary)); fakePtr = &portLibraryToTest; rc = omrport_init_library(fakePtr, sizeof(OMRPortLibrary)); if (0 != rc) { outputErrorMessage(PORTTEST_ERROR_ARGS, "omrport_init_library() returned %d expected 0\n", rc); } /* Shut it down */ portLibraryToTest.port_shutdown_library(fakePtr); omrthread_detach(attachedThread); /* Global pointer should be NULL */ if (NULL != fakePtr->portGlobals) { outputErrorMessage(PORTTEST_ERROR_ARGS, "port_shutdown_library() portGlobal pointer is not NULL\n"); } /* Shutdown again, should be ok, nothing to check ... * TODO support this? portLibraryToTest.port_shutdown_library(fakePtr); */ /* Let's do it all over again, this time self allocated * Note a self allocated library does not startup, so there are no * port globals etc. Verifies the shutdown routines are safe */ fakePtr = NULL; rc = omrport_allocate_library(&fakePtr); if (0 != rc) { outputErrorMessage(PORTTEST_ERROR_ARGS, "omrport_allocate_library() returned %d expected 0\n", rc); goto exit; } /* TODO library not started, fair to shut it down ? fakePtr->port_shutdown_library(fakePtr); */ fakePtr = NULL; exit: reportTestExit(OMRPORTLIB, testName); }
omr_error_t OMR_MethodDictionary::insert(OMR_MethodDictionaryEntry *entry) { omr_error_t rc = OMR_ERROR_NONE; omrthread_t self = NULL; if (0 == omrthread_attach_ex(&self, J9THREAD_ATTR_DEFAULT)) { if (0 == omrthread_monitor_enter_using_threadId(_lock, self)) { OMR_MethodDictionaryEntry *newEntry = (OMR_MethodDictionaryEntry *)hashTableAdd(_hashTable, entry); if (NULL == newEntry) { rc = OMR_ERROR_OUT_OF_NATIVE_MEMORY; } else { bool reusedEntry = false; if (!entryValueEquals(newEntry, entry)) { /* There was an existing hash table entry with the same key. * Overwrite its contents. */ traceInsertEntryReplace(newEntry); cleanupEntryStrings(newEntry, this); reusedEntry = true; } /* copy the entry strings */ rc = dupEntryStrings(newEntry, entry); if (OMR_ERROR_NONE == rc) { traceInsertEntrySuccess(newEntry); if (!reusedEntry) { _currentBytes += _sizeofEntry; } _currentBytes += countEntryNameBytesNeeded(newEntry); if (_currentBytes > _maxBytes) { _maxBytes = _currentBytes; _maxEntries = hashTableGetCount(_hashTable); } } } omrthread_monitor_exit_using_threadId(_lock, self); } else { rc = OMR_ERROR_INTERNAL; } omrthread_detach(self); } else { rc = OMR_ERROR_FAILED_TO_ATTACH_NATIVE_THREAD; } if (OMR_ERROR_NONE != rc) { traceInsertEntryFailed(rc, entry); } return rc; }
int main(void) { int32_t totalFiles = 0; intptr_t rc = 0; char resultBuffer[128]; uintptr_t rcFile; uintptr_t handle; OMRPortLibrary portLibrary; rc = omrthread_attach_ex(NULL, J9THREAD_ATTR_DEFAULT); if (0 != rc) { fprintf(stderr, "omrthread_attach_ex(NULL, J9THREAD_ATTR_DEFAULT) failed, rc=%d\n", (int)rc); return -1; } rc = omrport_init_library(&portLibrary, sizeof(OMRPortLibrary)); if (0 != rc) { fprintf(stderr, "omrport_init_library(&portLibrary, sizeof(OMRPortLibrary)), rc=%d\n", (int)rc); return -1; } OMRPORT_ACCESS_FROM_OMRPORT(&portLibrary); rcFile = handle = omrfile_findfirst(SRC_DIR, resultBuffer); if(rcFile == (uintptr_t)-1) { fprintf(stderr, "omrfile_findfirst(SRC_DIR, resultBuffer), return code=%d\n", (int)rcFile); return -1; } while ((uintptr_t)-1 != rcFile) { if (strncmp(resultBuffer, VERBOSE_GC_FILE_PREFIX, strlen(VERBOSE_GC_FILE_PREFIX)) == 0) { analyze(resultBuffer, portLibrary); totalFiles++; /* Clean up verbose log file */ omrfile_unlink(resultBuffer); } rcFile = omrfile_findnext(handle, resultBuffer); } if (handle != (uintptr_t)-1) { omrfile_findclose(handle); } if(totalFiles < 1) { omrtty_printf("Failed to find any verbose GC file to process!\n\n"); } portLibrary.port_shutdown_library(&portLibrary); omrthread_detach(NULL); }
/** * PortLibrary shutdown. * * Shutdown the port library, de-allocate resources required by the components of the portlibrary. * Any resources that were created by @ref omrport_startup_library should be destroyed here. * * @param[in] portLibrary The portlibrary. * * @return 0 on success, negative return code on failure */ int32_t omrport_shutdown_library(struct OMRPortLibrary *portLibrary) { /* Ensure that the current thread is attached. * If it is not, there will be a crash trying to using * thread functions in the following shutdown functions. */ omrthread_t attached_thread = NULL; intptr_t rc = omrthread_attach_ex(&attached_thread, J9THREAD_ATTR_DEFAULT); if (0 != rc) { return (int32_t)rc; } #if defined(OMR_OPT_CUDA) portLibrary->cuda_shutdown(portLibrary); #endif /* OMR_OPT_CUDA */ portLibrary->introspect_shutdown(portLibrary); portLibrary->sig_shutdown(portLibrary); portLibrary->str_shutdown(portLibrary); /* vmem shutdown now requires sl support.*/ portLibrary->vmem_shutdown(portLibrary); portLibrary->sl_shutdown(portLibrary); portLibrary->sysinfo_shutdown(portLibrary); portLibrary->exit_shutdown(portLibrary); portLibrary->dump_shutdown(portLibrary); portLibrary->time_shutdown(portLibrary); /* Shutdown the socket library before the tty, so it can write to the tty if required */ portLibrary->nls_shutdown(portLibrary); portLibrary->mmap_shutdown(portLibrary); portLibrary->tty_shutdown(portLibrary); portLibrary->file_shutdown(portLibrary); portLibrary->file_blockingasync_shutdown(portLibrary); portLibrary->cpu_shutdown(portLibrary); portLibrary->error_shutdown(portLibrary); omrport_tls_shutdown(portLibrary); portLibrary->mem_shutdown(portLibrary); omrthread_detach(attached_thread); /* Last thing to do. If this port library was self allocated free this memory */ if (NULL != portLibrary->self_handle) { omrmem_deallocate_portLibrary(portLibrary); } return (int32_t)0; }
void OMR_MethodDictionary::cleanup() { if (NULL != _vm) { omrthread_t self = NULL; if (0 == omrthread_attach_ex(&self, J9THREAD_ATTR_DEFAULT)) { Trc_OMRPROF_methodDictionaryHighWaterMark(_maxBytes, _maxEntries, _sizeofEntry, _maxBytes - (_maxEntries * _sizeofEntry)); if (NULL != _hashTable) { hashTableForEachDo(_hashTable, OMR_MethodDictionary::cleanupEntryStrings, this); hashTableFree(_hashTable); _hashTable = NULL; } if (NULL != _lock) { omrthread_monitor_destroy(_lock); _lock = NULL; } _vm = NULL; omrthread_detach(self); } } }
omr_error_t OMR_MethodDictionary::init(OMR_VM *vm, size_t numProperties, const char * const *propertyNames) { _lock = NULL; _hashTable = NULL; _currentBytes = 0; _maxBytes = 0; _maxEntries = 0; _vm = vm; _numProperties = numProperties; _propertyNames = propertyNames; _sizeofEntry = (uint32_t)(sizeof(OMR_MethodDictionaryEntry) + (_numProperties * sizeof(char *))); omr_error_t rc = OMR_ERROR_NONE; omrthread_t self = NULL; if (0 == omrthread_attach_ex(&self, J9THREAD_ATTR_DEFAULT)) { OMRPORT_ACCESS_FROM_OMRVM(vm); _hashTable = hashTableNew( OMRPORTLIB, OMR_GET_CALLSITE(), 0, _sizeofEntry, 0, 0, OMRMEM_CATEGORY_OMRTI, entryHash, entryEquals, NULL, NULL); if (NULL != _hashTable) { if (0 != omrthread_monitor_init_with_name(&_lock, 0, "omrVM->_methodDictionary")) { rc = OMR_ERROR_FAILED_TO_ALLOCATE_MONITOR; } } else { rc = OMR_ERROR_OUT_OF_NATIVE_MEMORY; } if (OMR_ERROR_NONE != rc) { cleanup(); } omrthread_detach(self); } else { rc = OMR_ERROR_FAILED_TO_ATTACH_NATIVE_THREAD; } return rc; }
int testMain(int argc, char ** argv, char **envp) { /* Start up */ OMR_VM_Example exampleVM; OMR_VMThread *omrVMThread = NULL; omrthread_t self = NULL; exampleVM._omrVM = NULL; exampleVM.rootTable = NULL; /* Initialize the VM */ omr_error_t rc = OMR_Initialize(&exampleVM, &exampleVM._omrVM); Assert_MM_true(OMR_ERROR_NONE == rc); /* Recursive omrthread_attach() (i.e. re-attaching a thread that is already attached) is cheaper and less fragile * than non-recursive. If performing a sequence of function calls that are likely to attach & detach internally, * it is more efficient to call omrthread_attach() before the entire block. */ int j9rc = (int) omrthread_attach_ex(&self, J9THREAD_ATTR_DEFAULT); Assert_MM_true(0 == j9rc); /* Initialize root table */ exampleVM.rootTable = hashTableNew( exampleVM._omrVM->_runtime->_portLibrary, OMR_GET_CALLSITE(), 0, sizeof(RootEntry), 0, 0, OMRMEM_CATEGORY_MM, rootTableHashFn, rootTableHashEqualFn, NULL, NULL); /* Initialize heap and collector */ { /* This has to be done in local scope because MM_StartupManager has a destructor that references the OMR VM */ MM_StartupManagerImpl startupManager(exampleVM._omrVM); rc = OMR_GC_IntializeHeapAndCollector(exampleVM._omrVM, &startupManager); } Assert_MM_true(OMR_ERROR_NONE == rc); /* Attach current thread to the VM */ rc = OMR_Thread_Init(exampleVM._omrVM, NULL, &omrVMThread, "GCTestMailThread"); Assert_MM_true(OMR_ERROR_NONE == rc); /* Kick off the dispatcher therads */ rc = OMR_GC_InitializeDispatcherThreads(omrVMThread); Assert_MM_true(OMR_ERROR_NONE == rc); OMRPORT_ACCESS_FROM_OMRVM(exampleVM._omrVM); omrtty_printf("VM/GC INITIALIZED\n"); /* Do stuff */ MM_EnvironmentBase *env = MM_EnvironmentBase::getEnvironment(omrVMThread); MM_ObjectAllocationInterface *allocationInterface = env->_objectAllocationInterface; MM_GCExtensionsBase *extensions = env->getExtensions(); omrtty_printf("configuration is %s\n", extensions->configuration->getBaseVirtualTypeId()); omrtty_printf("collector interface is %s\n", env->getExtensions()->collectorLanguageInterface->getBaseVirtualTypeId()); omrtty_printf("garbage collector is %s\n", env->getExtensions()->getGlobalCollector()->getBaseVirtualTypeId()); omrtty_printf("allocation interface is %s\n", allocationInterface->getBaseVirtualTypeId()); /* Allocate objects without collection until heap exhausted */ uintptr_t allocatedFlags = 0; uintptr_t size = extensions->objectModel.adjustSizeInBytes(24); MM_AllocateDescription mm_allocdescription(size, allocatedFlags, true, true); uintptr_t allocatedCount = 0; while (true) { omrobjectptr_t obj = (omrobjectptr_t)allocationInterface->allocateObject(env, &mm_allocdescription, env->getMemorySpace(), false); if (NULL != obj) { extensions->objectModel.setObjectSize(obj, mm_allocdescription.getBytesRequested()); RootEntry rEntry = {"root1", obj}; RootEntry *entryInTable = (RootEntry *)hashTableAdd(exampleVM.rootTable, &rEntry); if (NULL == entryInTable) { omrtty_printf("failed to add new root to root table!\n"); } /* update entry if it already exists in table */ entryInTable->rootPtr = obj; allocatedCount++; } else { break; } } /* Print/verify thread allocation stats before GC */ MM_AllocationStats *allocationStats = allocationInterface->getAllocationStats(); omrtty_printf("thread allocated %d tlh bytes, %d non-tlh bytes, from %d allocations before NULL\n", allocationStats->tlhBytesAllocated(), allocationStats->nontlhBytesAllocated(), allocatedCount); uintptr_t allocationTotalBytes = allocationStats->tlhBytesAllocated() + allocationStats->nontlhBytesAllocated(); uintptr_t allocatedTotalBytes = size * allocatedCount; Assert_MM_true(allocatedTotalBytes == allocationTotalBytes); /* Force GC to print verbose system allocation stats -- should match thread allocation stats from before GC */ omrobjectptr_t obj = (omrobjectptr_t)allocationInterface->allocateObject(env, &mm_allocdescription, env->getMemorySpace(), true); env->unwindExclusiveVMAccessForGC(); Assert_MM_false(NULL == obj); extensions->objectModel.setObjectSize(obj, mm_allocdescription.getBytesRequested()); omrtty_printf("ALL TESTS PASSED\n"); /* Shut down */ /* Shut down the dispatcher therads */ rc = OMR_GC_ShutdownDispatcherThreads(omrVMThread); Assert_MM_true(OMR_ERROR_NONE == rc); /* Shut down collector */ rc = OMR_GC_ShutdownCollector(omrVMThread); Assert_MM_true(OMR_ERROR_NONE == rc); /* Detach from VM */ rc = OMR_Thread_Free(omrVMThread); Assert_MM_true(OMR_ERROR_NONE == rc); /* Shut down heap */ rc = OMR_GC_ShutdownHeap(exampleVM._omrVM); Assert_MM_true(OMR_ERROR_NONE == rc); /* Free root hash table */ hashTableFree(exampleVM.rootTable); /* Balance the omrthread_attach_ex() issued above */ omrthread_detach(self); /* Shut down VM * This destroys the port library and the omrthread library. * Don't use any port library or omrthread functions after this. * * (This also shuts down trace functionality, so the trace assertion * macros might not work after this.) */ rc = OMR_Shutdown(exampleVM._omrVM); Assert_MM_true(OMR_ERROR_NONE == rc); return rc; }
int main(int argc, char *argv[]) { omrthread_attach(NULL); OMRPortLibrary portLibrary; omrport_init_library(&portLibrary, sizeof(portLibrary)); DDR_RC rc = DDR_RC_OK; /* Get options. */ const char *macroFile = "src/macros/test/macroList"; const char *supersetFile = "superset.out"; const char *blobFile = "blob.dat"; const char *overrideFile = NULL; vector<string> debugFiles; rc = getOptions(&portLibrary, argc, argv, ¯oFile, &supersetFile, &blobFile, &overrideFile, &debugFiles); /* Create IR from input. */ #if defined(_MSC_VER) PdbScanner scanner; #else /* defined(_MSC_VER) */ DwarfScanner scanner; #endif /* defined(_MSC_VER) */ Symbol_IR ir; if ((DDR_RC_OK == rc) && !debugFiles.empty()) { rc = scanner.startScan(&portLibrary, &ir, &debugFiles); } /* Compute field offsets for UDTs. */ if (DDR_RC_OK == rc) { rc = ir.computeOffsets(); } /* Remove duplicate types. */ if (DDR_RC_OK == rc) { rc = ir.removeDuplicates(); } MacroTool macroTool; /* Read macros. */ if ((DDR_RC_OK == rc) && (NULL != macroFile)) { rc = macroTool.getMacros(macroFile); } /* Add Macros to IR. */ if (DDR_RC_OK == rc) { rc = macroTool.addMacrosToIR(&ir); } /* Apply Type Overrides; must be after scanning and loading macros. */ if ((DDR_RC_OK == rc) && (NULL != overrideFile)) { rc = ir.applyOverrideList(&portLibrary, overrideFile); } /* Generate output. */ if ((DDR_RC_OK == rc) && !ir._types.empty()) { rc = genBlob(&portLibrary, &ir, supersetFile, blobFile); } portLibrary.port_shutdown_library(&portLibrary); omrthread_detach(NULL); omrthread_shutdown_library(); return 0; }
/** * Verify port library management. * * The port library requires a region of memory for it's function table pointer. * This table must not be declared on a stack that is torn down prior to the application * running to completion and tearing down the port library. It can either be * created as a global variable to the program, or if a running port library is * present it can be allocated on behalf of the application. Self allocating * port libraries use the exported function * @ref omrport.c::omrport_allocate_library "omrport_allocate_library()". * This function allocates, initializes and starts the port library. * The port library is responsible for deallocation of this memory * as part of it's shutdown. */ TEST(PortTest, port_test5) { OMRPORT_ACCESS_FROM_OMRPORT(portTestEnv->getPortLibrary()); const char *testName = "omrport_test5"; OMRPortLibrary *fakePortLibrary = NULL; int32_t rc; omrthread_t attachedThread = NULL; reportTestEntry(OMRPORTLIB, testName); if (0 != omrthread_attach_ex(&attachedThread, J9THREAD_ATTR_DEFAULT)) { outputErrorMessage(PORTTEST_ERROR_ARGS, "Failed to attach to omrthread\n"); goto exit; } /* Pass */ fakePortLibrary = NULL; rc = omrport_allocate_library(&fakePortLibrary); if (0 != rc) { outputErrorMessage(PORTTEST_ERROR_ARGS, "omrport_allocate_library() returned %d expected 0\n", rc); goto exit; } /* Verify we have a pointer */ if (NULL == fakePortLibrary) { outputErrorMessage(PORTTEST_ERROR_ARGS, "omrport_allocate_library() returned NULL pointer\n"); goto exit; } /* Verify not started */ if (NULL != fakePortLibrary->portGlobals) { outputErrorMessage(PORTTEST_ERROR_ARGS, "omrport_allocate_library() portGlobals pointer is not NULL\n"); } /* Verify self allocated */ if (NULL == fakePortLibrary->self_handle) { outputErrorMessage(PORTTEST_ERROR_ARGS, "omrport_allocate_library() self_handle pointer is NULL\n"); } /* Verify it will start */ rc = omrport_startup_library(fakePortLibrary); if (0 != rc) { outputErrorMessage(PORTTEST_ERROR_ARGS, "omrport_startup_library() returned %d expected 0\n", rc); } /* Take this port library down */ fakePortLibrary->port_shutdown_library(fakePortLibrary); /* Try again, but force failure during startup by over riding one of the startup functions */ fakePortLibrary = NULL; rc = omrport_allocate_library(&fakePortLibrary); if (0 != rc) { outputErrorMessage(PORTTEST_ERROR_ARGS, "omrport_allocate_library() returned %d expected 0\n", rc); goto exit; } /* Override omrmem_startup */ fakePortLibrary->mem_startup = fake_mem_startup; rc = omrport_startup_library(fakePortLibrary); if (failMemStartup != rc) { outputErrorMessage(PORTTEST_ERROR_ARGS, "omrport_startup_library() returned %d expected %d\n", rc, failMemStartup); } /* No way to tell if it freed the memory properly. The pointer we have to the port library is * not updated as part of omrport_startup_library(), so we are now pointing at dead memory. * * NULL our pointer to exit can clean-up if required */ fakePortLibrary = NULL; exit: if (NULL != fakePortLibrary) { fakePortLibrary->port_shutdown_library(fakePortLibrary); } if (NULL != attachedThread) { omrthread_detach(attachedThread); } reportTestExit(OMRPORTLIB, testName); }
/** * Verify port library management. * * The second stage in starting a port library. Once a port library table has * been created via * @ref omrport.c::omrport_create_library "omrport_create_library()" * it is started via the exported function * @ref omrport.c::omrport_startup_library "omrport_startup_library()". * * @see omrport.c::omrport_create_library "omrport_create_library()" * @see omrport.c::omrport_init_library "omrport_init_library()" */ TEST(PortTest, port_test3) { OMRPORT_ACCESS_FROM_OMRPORT(portTestEnv->getPortLibrary()); const char *testName = "omrport_test3"; OMRPortLibrary *fakePtr = &portLibraryToTest; int32_t rc; omrthread_t attachedThread = NULL; reportTestEntry(OMRPORTLIB, testName); if (0 != omrthread_attach_ex(&attachedThread, J9THREAD_ATTR_DEFAULT)) { outputErrorMessage(PORTTEST_ERROR_ARGS, "Failed to attach to omrthread\n"); goto exit; } /* create a library and ensure the port globals is non NULL, what else can we do? */ memset(&portLibraryToTest, '0', sizeof(OMRPortLibrary)); rc = omrport_create_library(fakePtr, sizeof(OMRPortLibrary)); if (0 != rc) { outputErrorMessage(PORTTEST_ERROR_ARGS, "omrport_create_library() returned %d expected 0\n", rc); goto exit; } /* check the rc */ rc = omrport_startup_library(fakePtr); if (0 != rc) { outputErrorMessage(PORTTEST_ERROR_ARGS, "omrport_startup_library() returned %d expected 0\n", rc); } /* check portGlobals were allocated */ if (NULL == fakePtr->portGlobals) { outputErrorMessage(PORTTEST_ERROR_ARGS, "omrport_startup_library() portGlobals not allocated\n"); } if (NULL != fakePtr->self_handle) { outputErrorMessage(PORTTEST_ERROR_ARGS, "omrport_startup_library() self_handle pointer not NULL\n"); } /* Clean this port library up */ portLibraryToTest.port_shutdown_library(fakePtr); /* Do it again, but before starting override memory (first startup function) and * ensure everything is ok */ memset(&portLibraryToTest, '0', sizeof(OMRPortLibrary)); rc = omrport_create_library(fakePtr, sizeof(OMRPortLibrary)); if (0 != rc) { outputErrorMessage(PORTTEST_ERROR_ARGS, "omrport_create_library() returned %d expected 0\n", rc); goto exit; } /* override time_startup */ fakePtr->time_startup = fake_time_startup; rc = omrport_startup_library(fakePtr); if (failMemStartup != rc) { outputErrorMessage(PORTTEST_ERROR_ARGS, "omrport_startup_library() returned %d expected %d\n", rc, failMemStartup); } exit: portLibraryToTest.port_shutdown_library(fakePtr); if (NULL != attachedThread) { omrthread_detach(attachedThread); } reportTestExit(OMRPORTLIB, testName); }