/* @internal * * Creates a new buffer whose size is 512 bytes larger than the original one. * Copies over the specified contents from the original buffer to the new one, and frees the original buffer. * * The new buffer must be freed using omrmem_free_memory. * * @param[in] portLibrary The port library. * @param[in] stackBuf Pointer to the stack buffer. * @param[in,out] bufStart Pointer to the beginning of the original buffer. * @param[in,out] cursor Contents of the original buffer up to, but not including cursor will be copied to the new buffer. * cursor is updated to have the same offset in the new buffer. * @param[in,out] bytesLeft Remaining bytes of the original buffer. Updated to be the remaining bytes of the newly allocated buffer * @param[in,out] outBufLen Size of the original buffer. * * @return 0 on success, -1 on failure (out of memory). */ static int growBuffer(struct OMRPortLibrary *portLibrary, char *stackBuf, char **bufStart, char **cursor, size_t *bytesLeft, uintptr_t *bufLen) { #define SIZE_OF_INCREMENT 512 char *newBuf = NULL; *bufLen = *bufLen + SIZE_OF_INCREMENT; newBuf = portLibrary->mem_allocate_memory(portLibrary, *bufLen, OMR_GET_CALLSITE(), OMRMEM_CATEGORY_PORT_LIBRARY); if (newBuf == NULL) { return -1; } /* copy over the work we've already done */ memcpy(newBuf, *bufStart, *cursor - *bufStart); if (*bufStart != stackBuf) { portLibrary->mem_free_memory(portLibrary, *bufStart); } /* set up the new buffer */ *bytesLeft = *bufLen - (*cursor - *bufStart); *cursor = newBuf + (*cursor - *bufStart); *bufStart = newBuf; return 0; #undef SIZE_OF_INCREMENT }
static J9Pool * createNewPool(OMRPortLibrary *portLib, PoolInputData *input) { uint32_t expectedNumElems = (input->numberElements == 0) ? 1 : input->numberElements; uint32_t expectedAlignment = (input->elementAlignment == 0) ? MIN_GRANULARITY : input->elementAlignment; J9Pool *pool = pool_new( input->structSize, input->numberElements, input->elementAlignment, input->poolFlags, OMR_GET_CALLSITE(), OMRMEM_CATEGORY_VM, POOL_FOR_PORT(portLib)); /* Check that creation succeeded */ if (NULL == pool) { return NULL; } if (pool->puddleAllocSize < ((expectedNumElems * ROUND_TO(expectedAlignment, input->structSize)) + ROUND_TO(expectedAlignment, sizeof(J9PoolPuddle)))) { pool_kill(pool); return NULL; } else if ((input->poolFlags & POOL_ROUND_TO_PAGE_SIZE) && (pool->puddleAllocSize < OS_PAGE_SIZE)) { pool_kill(pool); return NULL; } return pool; }
/* * Prepares the specified hook interface for first use. * * This function may be called directly. * * Returns 0 on success, non-zero on failure */ intptr_t J9HookInitializeInterface(struct J9HookInterface **hookInterface, OMRPortLibrary *portLib, size_t interfaceSize) { J9CommonHookInterface *commonInterface = (J9CommonHookInterface *)hookInterface; memset(commonInterface, 0, interfaceSize); commonInterface->hookInterface = (J9HookInterface *)GLOBAL_TABLE(hookFunctionTable); commonInterface->size = interfaceSize; if (omrthread_monitor_init_with_name(&commonInterface->lock, 0, "Hook Interface")) { J9HookShutdownInterface(hookInterface); return J9HOOK_ERR_NOMEM; } commonInterface->pool = pool_new(sizeof(J9HookRecord), 0, 0, 0, OMR_GET_CALLSITE(), OMRMEM_CATEGORY_VM, POOL_FOR_PORT((OMRPortLibrary *)portLib)); if (commonInterface->pool == NULL) { J9HookShutdownInterface(hookInterface); return J9HOOK_ERR_NOMEM; } commonInterface->nextAgentID = J9HOOK_AGENTID_DEFAULT + 1; commonInterface->portLib = portLib; commonInterface->threshold4Trace = OMRHOOK_DEFAULT_THRESHOLD_IN_MILLISECONDS_WARNING_CALLBACK_ELAPSED_TIME; commonInterface->eventSize = (interfaceSize - sizeof(J9CommonHookInterface)) / (sizeof(U_8) + sizeof(OMREventInfo4Dump) + sizeof(J9HookRecord*)); return 0; }
static intptr_t file_write_using_wctomb(struct OMRPortLibrary *portLibrary, intptr_t fd, const char *buf, intptr_t nbytes) { intptr_t result = 0; intptr_t newLength = 0; char stackBuf[512]; char *newBuf = stackBuf; newLength = walkUTF8String((uint8_t *)buf, nbytes); if (0 != newLength) { if (newLength > sizeof(stackBuf)) { newBuf = portLibrary->mem_allocate_memory(portLibrary, newLength, OMR_GET_CALLSITE(), OMRMEM_CATEGORY_PORT_LIBRARY); } if (NULL != newBuf) { translateUTF8String((uint8_t *)buf, (uint8_t *)newBuf, nbytes); buf = newBuf; nbytes = newLength; } } result = portLibrary->file_write(portLibrary, fd, (void *)buf, nbytes); if (newBuf != stackBuf && newBuf != NULL) { portLibrary->mem_free_memory(portLibrary, newBuf); } return (result == nbytes) ? 0 : result; }
/* * Prepares the specified hook interface for first use. * * This function may be called directly. * * Returns 0 on success, non-zero on failure */ intptr_t J9HookInitializeInterface(struct J9HookInterface **hookInterface, OMRPortLibrary *portLib, size_t interfaceSize) { J9CommonHookInterface *commonInterface = (J9CommonHookInterface *)hookInterface; memset(commonInterface, 0, interfaceSize); commonInterface->hookInterface = (J9HookInterface *)GLOBAL_TABLE(hookFunctionTable); commonInterface->size = interfaceSize; if (omrthread_monitor_init_with_name(&commonInterface->lock, 0, "Hook Interface")) { J9HookShutdownInterface(hookInterface); return J9HOOK_ERR_NOMEM; } commonInterface->pool = pool_new(sizeof(J9HookRecord), 0, 0, 0, OMR_GET_CALLSITE(), OMRMEM_CATEGORY_VM, POOL_FOR_PORT((OMRPortLibrary *)portLib)); if (commonInterface->pool == NULL) { J9HookShutdownInterface(hookInterface); return J9HOOK_ERR_NOMEM; } commonInterface->nextAgentID = J9HOOK_AGENTID_DEFAULT + 1; return 0; }
static void setPortableError(OMRPortLibrary *portLibrary, const char *funcName, int32_t portlibErrno, int systemErrno) { char *errmsgbuff = NULL; int32_t errmsglen = 0; int32_t portableErrno = portlibErrno + findError(systemErrno); /*Get size of str_printf buffer (it includes null terminator)*/ errmsglen = portLibrary->str_printf(portLibrary, NULL, 0, "%s%s", funcName, strerror(systemErrno)); if (errmsglen <= 0) { /*Set the error with no message*/ portLibrary->error_set_last_error(portLibrary, systemErrno, portableErrno); return; } /*Alloc the buffer*/ errmsgbuff = portLibrary->mem_allocate_memory(portLibrary, errmsglen, OMR_GET_CALLSITE(), OMRMEM_CATEGORY_PORT_LIBRARY); if (NULL == errmsgbuff) { /*Set the error with no message*/ portLibrary->error_set_last_error(portLibrary, systemErrno, portableErrno); return; } /*Fill the buffer using str_printf*/ portLibrary->str_printf(portLibrary, errmsgbuff, errmsglen, "%s%s", funcName, strerror(systemErrno)); /*Set the error message*/ portLibrary->error_set_last_error_with_message(portLibrary, portableErrno, errmsgbuff); /*Free the buffer*/ portLibrary->mem_free_memory(portLibrary, errmsgbuff); return; }
void omrfile_vprintf(struct OMRPortLibrary *portLibrary, intptr_t fd, const char *format, va_list args) { char localBuffer[256]; char *writeBuffer = NULL; uintptr_t bufferSize = 0; uintptr_t stringSize = 0; /* str_vprintf(.., NULL, ..) result is size of buffer required including the null terminator */ bufferSize = portLibrary->str_vprintf(portLibrary, NULL, 0, format, args); /* use local buffer if possible, allocate a buffer from system memory if local buffer not large enough */ if (sizeof(localBuffer) >= bufferSize) { writeBuffer = localBuffer; } else { writeBuffer = portLibrary->mem_allocate_memory(portLibrary, bufferSize, OMR_GET_CALLSITE(), OMRMEM_CATEGORY_PORT_LIBRARY); } /* format and write out the buffer (truncate into local buffer as last resort) without null terminator */ if (NULL != writeBuffer) { stringSize = portLibrary->str_vprintf(portLibrary, writeBuffer, bufferSize, format, args); portLibrary->file_write_text(portLibrary, fd, writeBuffer, stringSize); /* dispose of buffer if not on local */ if (writeBuffer != localBuffer) { portLibrary->mem_free_memory(portLibrary, writeBuffer); } } else { portLibrary->nls_printf(portLibrary, J9NLS_ERROR, J9NLS_PORT_FILE_MEMORY_ALLOCATE_FAILURE); stringSize = portLibrary->str_vprintf(portLibrary, localBuffer, sizeof(localBuffer), format, args); portLibrary->file_write_text(portLibrary, fd, localBuffer, stringSize); } }
/** * Re-allocate memory. * * @param[in] portLibrary The port library * @param[in] memoryPointer Base address of memory to be re-allocated. * @param[in] byteAmount Number of bytes to re-allocated. * @param[in] callSite Allocation callsite, or NULL if the callsite from the original allocation should be inherited * @param[in] category Memory allocation category code * * @return pointer to memory on success, NULL on error or if byteAmount * is 0 and memoryPointer is non-NULL * * @note if memoryPointer is NULL, this function will behave like mem_allocate_memory * for the specified byteAmount * * @note If byteAmount is 0 and memoryPointer is non-NULL, this function will * behave like mem_free_memory for the specified memoryPointer and * returns NULL * * @note If this function is unable to allocate the requested memory, the original * memory is not freed and may still be used. * * @internal @warning Do not call error handling code @ref omrerror upon error as * the error handling code uses per thread buffers to store the last error. If memory * can not be allocated the result would be an infinite loop. */ void * omrmem_reallocate_memory(struct OMRPortLibrary *portLibrary, void *memoryPointer, uintptr_t byteAmount, const char *callSite, uint32_t category) { void *pointer = NULL; uintptr_t allocationByteAmount; reallocate_memory_func_t reallocateFunction = omrmem_reallocate_memory_basic; Trc_PRT_mem_omrmem_reallocate_memory_Entry(memoryPointer, byteAmount, callSite, category); if (memoryPointer == NULL) { pointer = omrmem_allocate_memory(portLibrary, byteAmount, NULL == callSite ? OMR_GET_CALLSITE() : callSite, category); } else if (byteAmount == 0) { omrmem_free_memory(portLibrary, memoryPointer); } else { memoryPointer = unwrapBlockAndCheckTags(portLibrary, memoryPointer); if (NULL == callSite) { /* Inherit the callsite from the original allocation */ callSite = ((J9MemTag *) memoryPointer)->callSite; } allocationByteAmount = ROUNDED_BYTE_AMOUNT(byteAmount); pointer = reallocateFunction(portLibrary, memoryPointer, allocationByteAmount); if (NULL != pointer) { pointer = wrapBlockAndSetTags(portLibrary, pointer, byteAmount, callSite, category); } if (NULL == pointer) { Trc_PRT_mem_omrmem_reallocate_memory_failed_2(callSite, memoryPointer, allocationByteAmount); } } Trc_PRT_mem_omrmem_reallocate_memory_Exit(pointer); return pointer; }
J9Pool * MM_ConfigurationSegregated::createEnvironmentPool(MM_EnvironmentBase *env) { OMRPORT_ACCESS_FROM_OMRPORT(env->getPortLibrary()); uintptr_t numberOfElements = getConfigurationDelegate()->getInitialNumberOfPooledEnvironments(env); /* number of elements, pool flags = 0, 0 selects default pool configuration (at least 1 element, puddle size rounded to OS page size) */ return pool_new(sizeof(MM_EnvironmentBase), numberOfElements, sizeof(uint64_t), 0, OMR_GET_CALLSITE(), OMRMEM_CATEGORY_MM, POOL_FOR_PORT(OMRPORTLIB)); }
/** * Write formatted text to a file. * * Writes formatted output to the filestream. All text will be transliterated from modifed UTF-8 * to the platform encoding. * * @param[in] portLibrary The port library * @param[in] fileStream Filestream to write to * @param[in] format The format string. * @param[in] args Variable argument list. * * @internal @note Supported, portable format specifiers are described in the document entitled * "PortLibrary printf" in the "Inside J9" Lotus Notes database. */ void omrfilestream_vprintf(struct OMRPortLibrary *portLibrary, OMRFileStream *fileStream, const char *format, va_list args) { char outputBuffer[512]; char *allocatedBuffer = NULL; uintptr_t numberWritten = 0; va_list copyOfArgs; Trc_PRT_filestream_vprintf_Entry(fileStream, format); if ((NULL == fileStream) || (NULL == format)) { Trc_PRT_filestream_vprintf_invalidArgs(fileStream, format); Trc_PRT_filestream_vprintf_Exit(); return; } /* Attempt to write output to stack buffer */ COPY_VA_LIST(copyOfArgs, args); numberWritten = portLibrary->str_vprintf(portLibrary, outputBuffer, sizeof(outputBuffer), format, copyOfArgs); /* str_vprintf always null terminates, returns number characters written excluding the null terminator */ if (sizeof(outputBuffer) > (numberWritten + 1)) { /* write out the buffer */ portLibrary->filestream_write_text(portLibrary, fileStream, outputBuffer, numberWritten, J9STR_CODE_PLATFORM_RAW); Trc_PRT_filestream_vprintf_Exit(); return; } /* Either the buffer was too small, or it was the exact size. Unfortunately can't tell the difference, * need to determine the size of the buffer (another call to str_vprintf) then print to the buffer, * a third call to str_vprintf */ COPY_VA_LIST(copyOfArgs, args); /* What is size of buffer required ? Does not include the \0 */ numberWritten = portLibrary->str_vprintf(portLibrary, NULL, 0, format, copyOfArgs); numberWritten += 1; Trc_PRT_filestream_vprintf_stackBufferNotBigEnough(fileStream, format, numberWritten); allocatedBuffer = portLibrary->mem_allocate_memory(portLibrary, numberWritten, OMR_GET_CALLSITE(), OMRMEM_CATEGORY_PORT_LIBRARY); if (NULL == allocatedBuffer) { portLibrary->nls_printf(portLibrary, J9NLS_ERROR, J9NLS_PORT_FILE_MEMORY_ALLOCATE_FAILURE); Trc_PRT_filestream_vprintf_failedMalloc(fileStream, format, numberWritten); Trc_PRT_filestream_vprintf_Exit(); return; } numberWritten = portLibrary->str_vprintf(portLibrary, allocatedBuffer, numberWritten, format, args); portLibrary->filestream_write_text(portLibrary, fileStream, allocatedBuffer, numberWritten, J9STR_CODE_PLATFORM_RAW); portLibrary->mem_free_memory(portLibrary, allocatedBuffer); Trc_PRT_filestream_vprintf_Exit(); }
/** * Determines an absolute pathname for the executable. * * @param[in] portLibrary The port library. * @param[in] argv0 argv[0] value * @param[out] result Null terminated pathname string * * @return 0 on success, -1 on error (or information is not available). * * @note Caller should /not/ de-allocate memory in the result buffer, as string containing * the executable name is system-owned (managed internally by the port library). */ intptr_t omrsysinfo_get_executable_name(struct OMRPortLibrary *portLibrary, const char *argv0, char **result) { if (NULL == argv0) { return -1; } *result = (portLibrary->mem_allocate_memory)(portLibrary, strlen(argv0) + 1, OMR_GET_CALLSITE()); if (NULL == *result) { return -1; } strcpy(*result, argv0); return 0; }
/** * @internal * Write text to a file by transliterating it. * No parameter error checking. */ static intptr_t transliterate_write_text(struct OMRPortLibrary *portLibrary, OMRFileStream *fileStream, const char *buf, intptr_t nbytes, int32_t toEncoding) { char stackExpandedBuffer[512]; char *expandedBuffer = stackExpandedBuffer; uintptr_t convertedSize = 0; intptr_t rc = -1; /* The buffer must be MUTF8 */ int32_t fromEncoding = J9STR_CODE_MUTF8; /* Calculate the size of the buffer needed for the converted string. * If our buffer is not big enough, allocate a new one. */ rc = portLibrary->str_convert(portLibrary, fromEncoding, toEncoding, buf, nbytes, NULL, 0); if (rc < 0) { Trc_PRT_filestream_write_text_failedStringTransliteration(fileStream, buf, nbytes, toEncoding, (int32_t) rc); return OMRPORT_ERROR_FILE_OPFAILED; } else if ((size_t) rc > sizeof(stackExpandedBuffer)) { expandedBuffer = portLibrary->mem_allocate_memory(portLibrary, rc, OMR_GET_CALLSITE(), OMRMEM_CATEGORY_PORT_LIBRARY); if (NULL == expandedBuffer) { Trc_PRT_filestream_write_text_failedMalloc(fileStream, buf, nbytes, rc); return OMRPORT_ERROR_FILE_OPFAILED; } } convertedSize = rc; /* Fill the buffer with the new string */ rc = portLibrary->str_convert(portLibrary, fromEncoding, toEncoding, buf, nbytes, expandedBuffer, convertedSize); if (rc < 0) { Trc_PRT_filestream_write_text_failedStringTransliteration(fileStream, buf, nbytes, toEncoding, (int32_t) rc); rc = OMRPORT_ERROR_FILE_OPFAILED; } else { /* Write the converted bytes to the file, we will return whatever error/bytecount */ convertedSize = rc; rc = write_all(portLibrary, fileStream, expandedBuffer, convertedSize); if (rc < 0) { Trc_PRT_filestream_write_text_failedToWrite(fileStream, expandedBuffer, convertedSize, rc); } } /* free the buffer only if we had to malloc one, otherwise it is on the stack */ if (stackExpandedBuffer != expandedBuffer) { portLibrary->mem_free_memory(portLibrary, expandedBuffer); } return rc; }
/** * Create new instance of ConcurrentGCIncrementalUpdate object. * * @return Reference to new MM_ConcurrentGCIncrementalUpdate object or NULL */ MM_ConcurrentGCIncrementalUpdate * MM_ConcurrentGCIncrementalUpdate::newInstance(MM_EnvironmentBase *env) { MM_ConcurrentGCIncrementalUpdate *concurrentGC = (MM_ConcurrentGCIncrementalUpdate *)env->getForge()->allocate(sizeof(MM_ConcurrentGCIncrementalUpdate), OMR::GC::AllocationCategory::FIXED, OMR_GET_CALLSITE()); if (NULL != concurrentGC) { new(concurrentGC) MM_ConcurrentGCIncrementalUpdate(env); if (!concurrentGC->initialize(env)) { concurrentGC->kill(env); concurrentGC = NULL; } } return concurrentGC; }
/** * Initialization */ MM_CollectorLanguageInterfaceImpl* MM_CollectorLanguageInterfaceImpl::newInstance(MM_EnvironmentBase* env) { MM_CollectorLanguageInterfaceImpl* cli = NULL; OMR_VM* omrVM = env->getOmrVM(); MM_GCExtensionsBase* extensions = MM_GCExtensionsBase::getExtensions(omrVM); cli = (MM_CollectorLanguageInterfaceImpl*)extensions->getForge()->allocate( sizeof(MM_CollectorLanguageInterfaceImpl), OMR::GC::AllocationCategory::FIXED, OMR_GET_CALLSITE()); if (NULL != cli) { new (cli) MM_CollectorLanguageInterfaceImpl(omrVM); if (!cli->initialize(omrVM)) { cli->kill(env); cli = NULL; } } return cli; }
/** * Write to a file. * * Writes formatted output to the file referenced by the file descriptor. * * @param[in] portLibrary The port library * @param[in] fd File descriptor to write. * @param[in] format The format String. * @param[in] args Variable argument list. * * @internal @note Supported, portable format specifiers are described in the document entitled "PortLibrary printf" * in the "Inside J9" Lotus Notes database. */ void omrfile_vprintf(struct OMRPortLibrary *portLibrary, intptr_t fd, const char *format, va_list args) { char outputBuffer[256]; char *allocatedBuffer; uint32_t numberWritten; va_list copyOfArgs; /* Attempt to write output to stack buffer */ COPY_VA_LIST(copyOfArgs, args); numberWritten = portLibrary->str_vprintf(portLibrary, outputBuffer, sizeof(outputBuffer), format, copyOfArgs); /* str_vprintf always null terminates, returns number characters written excluding the null terminator */ if (sizeof(outputBuffer) > (numberWritten + 1)) { /* write out the buffer */ portLibrary->file_write_text(portLibrary, fd, outputBuffer, numberWritten); return; } /* Either the buffer was too small, or it was the exact size. Unfortunately can't tell the difference, * need to determine the size of the buffer (another call to str_vprintf) then print to the buffer, * a third call to str_vprintf */ COPY_VA_LIST(copyOfArgs, args); /* What is size of buffer required ? Does not include the \0 */ numberWritten = portLibrary->str_vprintf(portLibrary, NULL, (uint32_t)(-1), format, copyOfArgs); numberWritten += 1; allocatedBuffer = portLibrary->mem_allocate_memory(portLibrary, numberWritten, OMR_GET_CALLSITE(), OMRMEM_CATEGORY_PORT_LIBRARY); if (NULL == allocatedBuffer) { portLibrary->nls_printf(portLibrary, J9NLS_ERROR, J9NLS_PORT_FILE_MEMORY_ALLOCATE_FAILURE); return; } numberWritten = portLibrary->str_vprintf(portLibrary, allocatedBuffer, numberWritten, format, args); portLibrary->file_write_text(portLibrary, fd, allocatedBuffer, numberWritten); portLibrary->mem_free_memory(portLibrary, allocatedBuffer); }
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; }
MM_MemoryManager* MM_MemoryManager::newInstance(MM_EnvironmentBase* env) { MM_MemoryManager* memoryManager = (MM_MemoryManager*)env->getForge()->allocate(sizeof(MM_MemoryManager), OMR::GC::AllocationCategory::FIXED, OMR_GET_CALLSITE()); if (NULL != memoryManager) { new (memoryManager) MM_MemoryManager(env); if (!memoryManager->initialize(env)) { memoryManager->kill(env); memoryManager = NULL; } } return memoryManager; }
static void testRegisterWithAgent(OMRPortLibrary *portLib, uintptr_t *passCount, uintptr_t *failCount, J9HookInterface **hookInterface, uintptr_t event, uintptr_t agentID, uintptr_t userData, uintptr_t expectedResult) { OMRPORT_ACCESS_FROM_OMRPORT(portLib); if (((*hookInterface)->J9HookRegisterWithCallSite(hookInterface, event | J9HOOK_TAG_AGENT_ID, hookOrderedEvent, OMR_GET_CALLSITE(), (void *)userData, agentID) == 0) == (expectedResult == 0)) { (*passCount)++; } else { omrtty_printf("J9HookRegisterWithCallSite for 0x%zx %s. It should have %s.\n", event, (expectedResult ? "succeeded" : "failed"), (expectedResult ? "failed" : "succeeded")); (*failCount)++; } }
static void testRegister(OMRPortLibrary *portLib, uintptr_t *passCount, uintptr_t *failCount, J9HookInterface **hookInterface, uintptr_t event, uintptr_t expectedResult) { OMRPORT_ACCESS_FROM_OMRPORT(portLib); if (((*hookInterface)->J9HookRegisterWithCallSite(hookInterface, event, hookNormalEvent, OMR_GET_CALLSITE(), NULL) == 0) == (expectedResult == 0)) { (*passCount)++; } else { omrtty_printf("J9HookRegisterWithCallSite for 0x%zx %s. It should have %s.\n", event, (expectedResult ? "succeeded" : "failed"), (expectedResult ? "failed" : "succeeded")); (*failCount)++; } }
/** * Create a new MM_VerboseWriterFileLoggingSynchronous instance. * @return Pointer to the new MM_VerboseWriterFileLoggingSynchronous. */ MM_VerboseWriterFileLoggingSynchronous * MM_VerboseWriterFileLoggingSynchronous::newInstance(MM_EnvironmentBase *env, MM_VerboseManager *manager, char *filename, uintptr_t numFiles, uintptr_t numCycles) { MM_GCExtensionsBase *extensions = MM_GCExtensionsBase::getExtensions(env->getOmrVM()); MM_VerboseWriterFileLoggingSynchronous *agent = (MM_VerboseWriterFileLoggingSynchronous *)extensions->getForge()->allocate(sizeof(MM_VerboseWriterFileLoggingSynchronous), OMR::GC::AllocationCategory::DIAGNOSTIC, OMR_GET_CALLSITE()); if(agent) { new(agent) MM_VerboseWriterFileLoggingSynchronous(env, manager); if(!agent->initialize(env, filename, numFiles, numCycles)) { agent->kill(env); agent = NULL; } } return agent; }
MM_Configuration * MM_ConfigurationSegregated::newInstance(MM_EnvironmentBase *env) { MM_ConfigurationSegregated *configuration; configuration = (MM_ConfigurationSegregated *) env->getForge()->allocate(sizeof(MM_ConfigurationSegregated), MM_AllocationCategory::FIXED, OMR_GET_CALLSITE()); if(NULL != configuration) { new(configuration) MM_ConfigurationSegregated(env); if(!configuration->initialize(env)) { configuration->kill(env); configuration = NULL; } } return configuration; }
/** * Initialization */ MM_MemorySubSpaceGenerational * MM_MemorySubSpaceGenerational::newInstance(MM_EnvironmentBase *env, MM_MemorySubSpace *memorySubSpaceNew, MM_MemorySubSpace *memorySubSpaceOld, bool usesGlobalCollector, uintptr_t minimumSize, uintptr_t minimumSizeNew, uintptr_t initialSizeNew, uintptr_t maximumSizeNew, uintptr_t minimumSizeOld, uintptr_t initialSizeOld, uintptr_t maximumSizeOld, uintptr_t maximumSize) { MM_MemorySubSpaceGenerational *memorySubSpace; memorySubSpace = (MM_MemorySubSpaceGenerational *)env->getForge()->allocate(sizeof(MM_MemorySubSpaceGenerational), MM_AllocationCategory::FIXED, OMR_GET_CALLSITE()); if (memorySubSpace) { new(memorySubSpace) MM_MemorySubSpaceGenerational(env, memorySubSpaceNew, memorySubSpaceOld, usesGlobalCollector, minimumSize, minimumSizeNew, initialSizeNew, maximumSizeNew, minimumSizeOld, initialSizeOld, maximumSizeOld, maximumSize); if (!memorySubSpace->initialize(env)) { memorySubSpace->kill(env); memorySubSpace = NULL; } } return memorySubSpace; }
/** * Allocate and initialize a new instance of the receiver. * @return a new instance of the receiver, or NULL on failure. */ MM_SweepSchemeSegregated * MM_SweepSchemeSegregated::newInstance(MM_EnvironmentBase *env, MM_MarkMap *markMap) { MM_SweepSchemeSegregated *instance; instance = (MM_SweepSchemeSegregated *)env->getForge()->allocate(sizeof(MM_SweepSchemeSegregated), MM_AllocationCategory::FIXED, OMR_GET_CALLSITE()); if (NULL != instance) { new(instance) MM_SweepSchemeSegregated(env, markMap); if (!instance->initialize(env)) { instance->kill(env); instance = NULL; } } return instance; }
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; }
/** * Initialize a new ConcurrentGCIncrementalUpdate object. * Instantiate card table and concurrent RAS objects(if required) and initialize all * monitors required by concurrent. Allocate and initialize the concurrent helper thread * table. * * @return TRUE if initialization completed OK;FALSE otheriwse */ bool MM_ConcurrentGCIncrementalUpdate::initialize(MM_EnvironmentBase *env) { J9HookInterface** mmPrivateHooks = J9_HOOK_INTERFACE(_extensions->privateHookInterface); if (!MM_ConcurrentGC::initialize(env)) { goto error_no_memory; } if (!createCardTable(env)) { goto error_no_memory; } /* Register on any hook we are interested in */ (*mmPrivateHooks)->J9HookRegisterWithCallSite(mmPrivateHooks, J9HOOK_MM_PRIVATE_CARD_CLEANING_PASS_2_START, hookCardCleanPass2Start, OMR_GET_CALLSITE(), (void *)this); return true; error_no_memory: return false; }
/** * Write text to a filestream. This function will take a MUTF-8 encoded string, and convert it into * the specified encoding. This makes it suitable for printing human readable text to the console * or a file. * * Writes up to nbytes from the provided buffer to the file referenced by the filestream. * * @param[in] portLibrary The port library * @param[in] fileStream Filestream to write. * @param[in] buf Buffer to be written. * @param[in] nbytes Size of buffer. Must fit in a size_t. Must be positive. * @param[in] toEncoding The desired output encoding.The desired output encoding. May be any of the * output encodings accepted by omrstr_convert(). * * @return Number of bytes written from buf, negative portable error code on failure. This may not * be the number of bytes actually written to the file, which is locale specific. * * @note If an error occurred, the file position is unknown. */ intptr_t omrfilestream_write_text(struct OMRPortLibrary *portLibrary, OMRFileStream *fileStream, const char *buf, intptr_t nbytes, int32_t toEncoding) { intptr_t rc = 0; #if defined(CRLFNEWLINES) uintptr_t i = 0; uintptr_t j = 0; uintptr_t newlineCount = 0; char stackNewlineBuffer[512]; char *newlineBuffer = stackNewlineBuffer; #endif /* defined(CRLFNEWLINES) */ /* The buffer must be MUTF8 */ int32_t fromEncoding = J9STR_CODE_MUTF8; Trc_PRT_filestream_write_text_Entry(fileStream, buf, nbytes, toEncoding); if ((nbytes < 0) || (NULL == buf) || (NULL == fileStream)) { Trc_PRT_filestream_write_text_invalidArgs(fileStream, buf, nbytes, toEncoding); Trc_PRT_filestream_write_text_Exit(OMRPORT_ERROR_FILE_INVAL); return OMRPORT_ERROR_FILE_INVAL; } else if (0 == nbytes) { Trc_PRT_filestream_write_text_Exit(0); return 0; } #if defined(CRLFNEWLINES) /* We have to change the line endings. This must be done entirely before transliteration. */ /* Count the newlines */ for (i = 0; i < ((uintptr_t) nbytes); i++) { if (buf[i] == '\n') { newlineCount += 1; } } if (0 < newlineCount) { /* Every newline now requires 2 bytes */ uintptr_t bufferSize = ((uintptr_t) nbytes) + newlineCount; /* malloc a bigger buffer if it is needed */ if (bufferSize > sizeof(stackNewlineBuffer)) { newlineBuffer = portLibrary->mem_allocate_memory(portLibrary, bufferSize, OMR_GET_CALLSITE(), OMRMEM_CATEGORY_PORT_LIBRARY); if (NULL == newlineBuffer) { Trc_PRT_filestream_write_text_failedMalloc(fileStream, buf, nbytes, rc); Trc_PRT_filestream_write_text_Exit(OMRPORT_ERROR_FILE_OPFAILED); return OMRPORT_ERROR_FILE_OPFAILED; } } /* replace the newlines */ for (i = 0, j = 0; i < bufferSize; i++, j++) { if (buf[j] == '\n') { newlineBuffer[i] = '\r'; i += 1; } newlineBuffer[i] = buf[j]; } buf = newlineBuffer; nbytes = bufferSize; } #endif /* defined(CRLFNEWLINES) */ if (fromEncoding == toEncoding) { /* omrstr_convert() does not support MUTF-8 -> MUTF-8 conversion, so do not use it. * This has the side effect of not validating the string */ rc = write_all(portLibrary, fileStream, buf, nbytes); } else { rc = transliterate_write_text(portLibrary, fileStream, buf, nbytes, toEncoding); } #if defined(CRLFNEWLINES) /* free the buffer only if we had to malloc one, otherwise it is on the stack */ if (newlineBuffer != stackNewlineBuffer) { portLibrary->mem_free_memory(portLibrary, newlineBuffer); } #endif /* defined(CRLFNEWLINES) */ /* if rc is not an error code, then we assume we have written everything from the buffer. At * this point, we want to return the number of characters consumed from the input buffer, not the * bytes output to the file. */ if (rc > 0) { rc = nbytes; } Trc_PRT_filestream_write_text_Exit(rc); return rc; }
/** * Create a new instance of a sublist puddle. * Given the size of the element backing store, create and return a newly initialized sublist puddle. * * @return An initialized instance of a sublist puddle with backing store */ MM_SublistPuddle * MM_SublistPuddle::newInstance(MM_EnvironmentBase *env, uintptr_t size, MM_SublistPool *parent, OMR::GC::AllocationCategory::Enum category) { MM_SublistPuddle *puddle = (MM_SublistPuddle *) env->getForge()->allocate(size + sizeof(MM_SublistPuddle), category, OMR_GET_CALLSITE()); if(NULL == puddle) { return NULL; } puddle->initialize(env, size, parent); return puddle; }
/** * Instantiate a MM_WorkPacketsConcurrent * @param mode type of packets (used for getting the right overflow handler) * @return pointer to the new object */ MM_WorkPacketsConcurrent * MM_WorkPacketsConcurrent::newInstance(MM_EnvironmentBase *env) { MM_WorkPacketsConcurrent *workPackets = (MM_WorkPacketsConcurrent *)env->getForge()->allocate(sizeof(MM_WorkPacketsConcurrent), OMR::GC::AllocationCategory::WORK_PACKETS, OMR_GET_CALLSITE()); if (NULL != workPackets) { new(workPackets) MM_WorkPacketsConcurrent(env); if (!workPackets->initialize(env)) { workPackets->kill(env); workPackets = NULL; } } return workPackets; }
bool MM_NUMAManager::recacheNUMASupport(MM_EnvironmentBase *env) { bool result = true; if (NULL != _activeNodes) { env->getForge()->free(_activeNodes); _activeNodes = NULL; _activeNodeCount = 0; } if (NULL != _affinityLeaders) { env->getForge()->free(_affinityLeaders); _affinityLeaders = NULL; _affinityLeaderCount = 0; } if (NULL != _freeProcessorPoolNodes) { env->getForge()->free(_freeProcessorPoolNodes); _freeProcessorPoolNodes = NULL; _freeProcessorPoolNodeCount = 0; } _maximumNodeNumber = 0; uintptr_t nodeCount = 0; OMRPORT_ACCESS_FROM_OMRPORT(env->getPortLibrary()); if (_physicalNumaEnabled) { intptr_t detailResult = omrvmem_numa_get_node_details(NULL, &nodeCount); if (0 != detailResult) { /* something went wrong in the underlying call so ignore any NUMA count data we might have received */ nodeCount = 0; } } else { nodeCount = _simulatedNodeCount; } if (0 != nodeCount) { /* we want to support NUMA either via the machine's physical NUMA or our simulated (aka "purely logical") NUMA */ uintptr_t nodeArraySize = sizeof(J9MemoryNodeDetail) * nodeCount; _activeNodes = (J9MemoryNodeDetail *)env->getForge()->allocate(nodeArraySize, OMR::GC::AllocationCategory::FIXED, OMR_GET_CALLSITE()); if (NULL == _activeNodes) { result = false; } else { memset(_activeNodes, 0x0, nodeArraySize); _activeNodeCount = nodeCount; if (_physicalNumaEnabled) { /* we want REAL NUMA so ask the underlying system for node details */ intptr_t detailResult = omrvmem_numa_get_node_details(_activeNodes, &_activeNodeCount); Assert_MM_true(0 == detailResult); Assert_MM_true(_activeNodeCount == nodeCount); } else { /* we want to use "fake" NUMA so synthesize the array data */ for (uintptr_t i = 0; i < nodeCount; i++) { _activeNodes[i].j9NodeNumber = i + 1; _activeNodes[i].memoryPolicy = J9NUMA_PREFERRED; /* NOTE: if we ever start counting these resources to determine GC thread counts, this will have to be something other than "1" */ _activeNodes[i].computationalResourcesAvailable = 1; } } /* Sorting the array in j9NodeNumber ascending order. * This sorting is not really required, but gives us ability to make some stronger assertions later in the code */ J9_SORT(_activeNodes, _activeNodeCount, sizeof(J9MemoryNodeDetail), compareNodeNumberFunc); /* now that we have the total list of active nodes, identify the affinity leaders */ uintptr_t preferredWithCPU = 0; uintptr_t allowedWithCPU = 0; /* if "preferred" nodes exist, we will use them as the leaders and fall back to "allowed" if there aren't any so count both and choose them after the loop */ for (uintptr_t activeNodeIndex = 0; activeNodeIndex < _activeNodeCount; activeNodeIndex++) { uintptr_t cpu = _activeNodes[activeNodeIndex].computationalResourcesAvailable; if (0 != cpu) { J9MemoryState policy = _activeNodes[activeNodeIndex].memoryPolicy; if (J9NUMA_PREFERRED == policy) { preferredWithCPU += 1; } else if (J9NUMA_ALLOWED == policy) { allowedWithCPU += 1; } else { /* nodes with CPUs but DENIED bindings go into the free processor pool */ _freeProcessorPoolNodeCount += 1; } } /* since we are walking all the nodes, this is also the time to update the maximum node number */ _maximumNodeNumber = OMR_MAX(_maximumNodeNumber, _activeNodes[activeNodeIndex].j9NodeNumber); } J9MemoryState policyType = J9NUMA_PREFERRED; _affinityLeaderCount = preferredWithCPU; if (0 == _affinityLeaderCount) { _affinityLeaderCount = allowedWithCPU; policyType = J9NUMA_ALLOWED; } /* Affinity Leader array allocation and construction */ if (0 != _affinityLeaderCount) { uintptr_t affinityLeaderArraySize = sizeof(J9MemoryNodeDetail) * _affinityLeaderCount; _affinityLeaders = (J9MemoryNodeDetail *)env->getForge()->allocate(affinityLeaderArraySize, OMR::GC::AllocationCategory::FIXED, OMR_GET_CALLSITE()); if (NULL == _affinityLeaders) { result = false; } else { memset(_affinityLeaders, 0x0, affinityLeaderArraySize); uintptr_t nextIndex = 0; for (uintptr_t activeNodeIndex = 0; activeNodeIndex < _activeNodeCount; activeNodeIndex++) { if ((0 != _activeNodes[activeNodeIndex].computationalResourcesAvailable) && (policyType == _activeNodes[activeNodeIndex].memoryPolicy)) { Assert_MM_true(nextIndex < _affinityLeaderCount); _affinityLeaders[nextIndex] = _activeNodes[activeNodeIndex]; nextIndex += 1; } } Assert_MM_true(nextIndex == _affinityLeaderCount); } } /* Free Processor Pool array allocation and construction */ if (0 != _freeProcessorPoolNodeCount) { /* allocate a free processor pool */ uintptr_t processorPoolArraySize = sizeof(J9MemoryNodeDetail) * _freeProcessorPoolNodeCount; _freeProcessorPoolNodes = (J9MemoryNodeDetail *)env->getForge()->allocate(processorPoolArraySize, OMR::GC::AllocationCategory::FIXED, OMR_GET_CALLSITE()); if (NULL == _freeProcessorPoolNodes) { result = false; } else { memset(_freeProcessorPoolNodes, 0x0, processorPoolArraySize); uintptr_t nextIndex = 0; for (uintptr_t activeNodeIndex = 0; activeNodeIndex < _activeNodeCount; activeNodeIndex++) { if ((0 != _activeNodes[activeNodeIndex].computationalResourcesAvailable) && (J9NUMA_DENIED == _activeNodes[activeNodeIndex].memoryPolicy)) { Assert_MM_true(nextIndex < _freeProcessorPoolNodeCount); _freeProcessorPoolNodes[nextIndex] = _activeNodes[activeNodeIndex]; nextIndex += 1; } } Assert_MM_true(nextIndex == _freeProcessorPoolNodeCount); } } } } return result; }
/** * Create a new instance of MM_ConcurrentCardTableForWC object * * @param markingScheme - reference to the colllectors marking scheme * @param collector - reference to the collector itself * * @return reference to new MM_ConcurrentCardTableForWC object or NULL */ MM_ConcurrentCardTable * MM_ConcurrentCardTableForWC::newInstance(MM_EnvironmentBase *env, MM_Heap *heap, MM_MarkingScheme *markingScheme, MM_ConcurrentGC *collector) { MM_ConcurrentCardTableForWC *cardTable; cardTable = (MM_ConcurrentCardTableForWC *)env->getForge()->allocate(sizeof(MM_ConcurrentCardTableForWC), OMR::GC::AllocationCategory::FIXED, OMR_GET_CALLSITE()); if (NULL != cardTable) { new(cardTable) MM_ConcurrentCardTableForWC(env, markingScheme, collector); if (!cardTable->initialize(env, heap)) { cardTable->kill(env); return NULL; } } return cardTable; }