//-------------------------------------------------------------------------------------------------- le_result_t le_mcc_Init ( void ) { // Create a pool for Call objects MccCallPool = le_mem_CreatePool("MccCallPool", sizeof(struct le_mcc_Call)); le_mem_ExpandPool(MccCallPool, MCC_MAX_CALL); le_mem_SetDestructor(MccCallPool, CallDestructor); SessionRefPool = le_mem_CreatePool("SessionRefPool", sizeof(SessionRefNode_t)); le_mem_ExpandPool(SessionRefPool, MCC_MAX_CALL); // Create the Safe Reference Map to use for Call object Safe References. MccCallRefMap = le_ref_CreateMap("MccCallMap", MCC_MAX_CALL); // Initialize call wakeup source - succeeds or terminates caller WakeupSource = le_pm_NewWakeupSource(0, CALL_WAKEUP_SOURCE_NAME); CallStateEventId = le_event_CreateId("CallStateEventId", sizeof(le_mcc_CallRef_t)); // Register a handler function for Call Event indications if(pa_mcc_SetCallEventHandler(NewCallEventHandler) != LE_OK) { LE_CRIT("Add pa_mcc_SetCallEventHandler failed"); return LE_FAULT; } // Add a handler to the close session service le_msg_AddServiceCloseHandler( le_mcc_GetServiceRef(), CloseSessionEventHandler, NULL ); return LE_OK; }
//-------------------------------------------------------------------------------------------------- void msgService_Init ( void ) //-------------------------------------------------------------------------------------------------- { // Create and initialize the pool of Service objects. ServicePoolRef = le_mem_CreatePool("MessagingServices", sizeof(Service_t)); le_mem_ExpandPool(ServicePoolRef, MAX_EXPECTED_SERVICES); le_mem_SetDestructor(ServicePoolRef, ServiceDestructor); // Create and initialize the pool of event handlers objects. HandlerEventPoolRef = le_mem_CreatePool("HandlerEventPool", sizeof(SessionEventHandler_t)); le_mem_ExpandPool(HandlerEventPoolRef, MAX_EXPECTED_SERVICES*6); // Create safe reference map for add references. HandlersRefMap = le_ref_CreateMap("HandlersRef", MAX_EXPECTED_SERVICES*6); // Create the Service Map. ServiceMapRef = le_hashmap_Create("MessagingServices", MAX_EXPECTED_SERVICES, ComputeServiceIdHash, AreServiceIdsTheSame); // Create the key to be used to identify thread-local data records containing the Message // Reference when running a Service's message receive handler. int result = pthread_key_create(&ThreadLocalRxMsgKey, NULL); if (result != 0) { LE_FATAL("Failed to create thread local key: result = %d (%s).", result, strerror(result)); } }
//-------------------------------------------------------------------------------------------------- void thread_Init ( void ) { // Create the thread memory pool. ThreadPool = le_mem_CreatePool("Thread Pool", sizeof(ThreadObj_t)); le_mem_ExpandPool(ThreadPool, THREAD_POOL_SIZE); // Create the Safe Reference Map for Thread References. Lock(); ThreadRefMap = le_ref_CreateMap("ThreadRef", THREAD_POOL_SIZE); Unlock(); // Create the destructor object pool. DestructorObjPool = le_mem_CreatePool("DestructorObjs", sizeof(DestructorObj_t)); // Create the thread-local data key to be used to store a pointer to each thread object. LE_ASSERT(pthread_key_create(&ThreadLocalDataKey, NULL) == 0); // Create a Thread Object for the main thread (the thread running this function). ThreadObj_t* threadPtr = CreateThread("main", NULL, NULL); // Store the Thread Object pointer in thread-local storage so GetCurrentThreadPtr() can // find it later. LE_ASSERT(pthread_setspecific(ThreadLocalDataKey, threadPtr) == 0); }
//-------------------------------------------------------------------------------------------------- void* le_mem_ForceAlloc ( le_mem_PoolRef_t pool ///< [IN] The pool from which the object is to be allocated. ) { LE_ASSERT(pool != NULL); void* objPtr; #ifndef LE_MEM_VALGRIND while ((objPtr = le_mem_TryAlloc(pool)) == NULL) { // Expand the pool. le_mem_ExpandPool(pool, pool->numBlocksToForce); Lock(); pool->numOverflows++; // log a warning. LE_DEBUG("Memory pool '%s' overflowed. Expanded to %zu blocks.", pool->name, pool->totalBlocks); Unlock(); } #else objPtr = le_mem_AssertAlloc(pool); #endif return objPtr; }
// ------------------------------------------------------------------------------------------------- void fjm_Start ( void ) // ------------------------------------------------------------------------------------------------- { LE_TEST_INFO("FJM TESTS START"); memset(TestResults, 0, sizeof(TestResults)); Counter = 0; // Compute the expected ending counter value. ExpectedCounterValue = GetExpectedCounterValue(); // Create semaphore to trigger CounterSemRef = le_sem_Create("CounterSem", 0); // Create the mutex. MutexRef = le_mutex_CreateNonRecursive("fork-join-mutex-test"); // Create the Context Pool. if (ContextPoolRef == NULL) { LE_TEST_INFO("Initializing FJM-ContextPool"); ContextPoolRef = le_mem_CreatePool("FJM-ContextPool", sizeof(Context_t)); le_mem_ExpandPool(ContextPoolRef, ExpectedCounterValue); } // Spawn the first child thread. SpawnChildren(1); }
//-------------------------------------------------------------------------------------------------- void atmachinestring_Init ( void ) { AtStringPool = le_mem_CreatePool("AtStringPool",sizeof(atmachinestring_t)); le_mem_ExpandPool(AtStringPool,DEFAULT_ATSTRING_POOL_SIZE); }
//-------------------------------------------------------------------------------------------------- void fa_event_Init ( void ) { // Create the pool from which Linux-specific thread record objects are allocated. PerThreadPool = le_mem_CreatePool("PerThreadEvent", sizeof(event_LinuxPerThreadRec_t)); le_mem_ExpandPool(PerThreadPool, LE_CONFIG_MAX_THREAD_POOL_SIZE); }
//-------------------------------------------------------------------------------------------------- void sem_Init ( void ) //-------------------------------------------------------------------------------------------------- { SemaphorePoolRef = le_mem_CreatePool("semaphore", sizeof(Semaphore_t)); le_mem_ExpandPool(SemaphorePoolRef, DEFAULT_POOL_SIZE); // Pass the change counter of list of semaphores to the Inspect tool. spy_SetListOfSemaphoresChgCntRef(&ListOfSemaphoresChgCntRef); }
//-------------------------------------------------------------------------------------------------- void ni_Init ( void ) //-------------------------------------------------------------------------------------------------- { LE_DEBUG("** Initialize Node Iterator subsystem."); IteratorPoolRef = le_mem_CreatePool(ITERATOR_POOL_NAME, sizeof(Iterator_t)); le_mem_ExpandPool(IteratorPoolRef, INITIAL_MAX_ITERATORS); IteratorRefMap = le_ref_CreateMap(ITERATOR_REF_MAP_NAME, INITIAL_MAX_ITERATORS*5); }
//-------------------------------------------------------------------------------------------------- void mem_Init ( void ) { // NOTE: No need to lock the mutex because this function should be called when there is still // only one thread running. // Create a memory for all sub-pools. SubPoolsPool = le_mem_CreatePool("SubPools", sizeof(MemPool_t)); le_mem_ExpandPool(SubPoolsPool, DEFAULT_SUB_POOLS_POOL_SIZE); // Pass the list of mem pools to the Inspect tool. spy_SetListOfPools(&ListOfPools); // Pass the change counter of list of mem pools to the Inspect tool. spy_SetListOfPoolsChgCntRef(&ListOfPoolsChgCntRef); }
//-------------------------------------------------------------------------------------------------- void fdMon_Init ( void ) //-------------------------------------------------------------------------------------------------- { // Create the FD Monitor Pool from which FD Monitor objects are to be allocated. /// @todo Make this configurable. FdMonitorPool = le_mem_CreatePool("FdMonitor", sizeof(FdMonitor_t)); le_mem_ExpandPool(FdMonitorPool, DEFAULT_FD_MONITOR_POOL_SIZE); // Create the Safe Reference Maps. /// @todo Make this configurable. FdMonitorRefMap = le_ref_CreateMap("FdMonitors", DEFAULT_FD_MONITOR_POOL_SIZE); HandlerRefMap = le_ref_CreateMap("FdEventHandlers", DEFAULT_FD_MONITOR_POOL_SIZE * LE_EVENT_NUM_FD_EVENT_TYPES); // Get a reference to the trace keyword that is used to control tracing in this module. TraceRef = le_log_GetTraceRef("fdMonitor"); }
//-------------------------------------------------------------------------------------------------- le_mem_PoolRef_t _le_mem_CreateSubPool ( le_mem_PoolRef_t superPool, ///< [IN] The super-pool. const char* componentName, ///< [IN] Name of the component. const char* name, ///< [IN] Name of the pool inside the component. size_t numObjects ///< [IN] The number of objects to take from the super-pool. ) { LE_ASSERT(superPool != NULL); // Make sure the parent pool is not itself a sub-pool. LE_ASSERT(superPool->superPoolPtr == NULL); // Get a sub-pool from the pool of sub-pools. le_mem_PoolRef_t subPool = le_mem_ForceAlloc(SubPoolsPool); // Initialize the pool. InitPool(subPool, componentName, name, superPool->userDataSize); subPool->superPoolPtr = superPool; Lock(); // Log an error if the pool name is not unique. VerifyUniquenessOfName(subPool); // Add the sub-pool to the list of pools. ListOfPoolsChgCnt++; le_dls_Queue(&ListOfPools, &(subPool->poolLink)); Unlock(); // Expand the pool to its initial size. // Note: This moves blocks from the parent pool to the sub pool, expanding the parent pool, // if necessary. le_mem_ExpandPool(subPool, numObjects); // Inherit the parent pool's destructor. subPool->destructor = superPool->destructor; return subPool; }
//-------------------------------------------------------------------------------------------------- le_result_t pa_sim_Init ( void ) { if (atports_GetInterface(ATPORT_COMMAND)==NULL) { LE_DEBUG("SIM Module is not initialize in this session"); return LE_NOT_POSSIBLE; } SimEventPoolRef = le_mem_CreatePool("SimEventPool", sizeof(pa_sim_Event_t)); SimEventPoolRef = le_mem_ExpandPool(SimEventPoolRef,DEFAULT_SIMEVENT_POOL_SIZE); EventUnsolicitedId = le_event_CreateId("SIMEventIdUnsol",sizeof(atmgr_UnsolResponse_t)); EventNewSimStateId = le_event_CreateIdWithRefCounting("SIMEventIdNewState"); le_event_AddHandler("SIMUnsolHandler",EventUnsolicitedId ,SIMUnsolHandler); LE_DEBUG_IF(SetIndicator()!=LE_OK,"cannot set sim +WIND indicator"); return LE_OK; }
//-------------------------------------------------------------------------------------------------- void fdMon_Init ( void ) //-------------------------------------------------------------------------------------------------- { // Create the FD Monitor Pool from which FD Monitor objects are to be allocated. /// @todo Make this configurable. FdMonitorPool = le_mem_CreatePool("FdMonitor", sizeof(FdMonitor_t)); le_mem_ExpandPool(FdMonitorPool, DEFAULT_FD_MONITOR_POOL_SIZE); // Create the Safe Reference Map. /// @todo Make this configurable. FdMonitorRefMap = le_ref_CreateMap("FdMonitors", DEFAULT_FD_MONITOR_POOL_SIZE); // Get a reference to the trace keyword that is used to control tracing in this module. TraceRef = le_log_GetTraceRef("fdMonitor"); // Create the thread-specific data key for the FD Monitor Ptr of the current running handler. LE_ASSERT(pthread_key_create(&FDMonitorPtrKey, NULL) == 0); }
//-------------------------------------------------------------------------------------------------- void dstr_Init ( void ) //-------------------------------------------------------------------------------------------------- { LE_DEBUG("** Initialize Dynamic String subsystem."); DynamicStringPoolRef = le_mem_CreatePool(CFG_DSTR_POOL_NAME, sizeof(Dstr_t)); le_mem_SetNumObjsToForce(DynamicStringPoolRef, 100); // Grow in chunks of 100 blocks. // For now (until pool config is added to the framework), set a minimum size. if (le_mem_GetObjectCount(DynamicStringPoolRef) != 0) { LE_WARN("TODO: Remove this code."); } else { le_mem_ExpandPool(DynamicStringPoolRef, 3000); } }
// ------------------------------------------------------------------------------------------------- void fjm_Start ( void* completionObjPtr ///< [in] Pointer to the object whose reference count is used to signal /// the completion of the test. ) // ------------------------------------------------------------------------------------------------- { // Compute the expected ending counter value. ExpectedCounterValue = GetExpectedCounterValue(); // Create the mutex. MutexRef = le_mutex_CreateNonRecursive("fork-join-mutex-test"); LE_INFO("completionObjPtr = %p.", completionObjPtr); // Create the Context Pool. ContextPoolRef = le_mem_CreatePool("FJM-ContextPool", sizeof(Context_t)); le_mem_ExpandPool(ContextPoolRef, ExpectedCounterValue); // Spawn the first child thread. SpawnChildren(1, completionObjPtr); }
//-------------------------------------------------------------------------------------------------- le_result_t pa_mrc_Init ( void ) { if (atports_GetInterface(ATPORT_COMMAND)==NULL) { LE_WARN("radio control Module is not initialize in this session"); return LE_NOT_POSSIBLE; } EventUnsolicitedId = le_event_CreateId("RCEventIdUnsol",sizeof(atmgr_UnsolResponse_t)); EventNewRcStatusId = le_event_CreateIdWithRefCounting("EventNewRcStatus"); le_event_AddHandler("RCUnsolHandler",EventUnsolicitedId ,CREGUnsolHandler); RegStatePoolRef = le_mem_CreatePool("regStatePool",sizeof(le_mrc_NetRegState_t)); RegStatePoolRef = le_mem_ExpandPool(RegStatePoolRef,DEFAULT_REGSTATE_POOL_SIZE); SubscribeUnsolCREG(PA_MRC_ENABLE_REG_LOC_NOTIFICATION); pa_mrc_GetNetworkRegConfig(&ThisMode); return LE_OK; }
static void TestPools ( le_mem_PoolRef_t idPool, ///< [IN] ID pool le_mem_PoolRef_t colourPool, ///< [IN] Colour pool le_mem_PoolRef_t stringPool ///< [IN] String pool ) { idObj_t* idsPtr[ID_POOL_SIZE + NUM_EXTRA_ID] = {NULL}; colourObj_t* coloursPtr[COLOUR_POOL_SIZE] = {NULL}; char* stringsPtr[4*STRING_POOL_SIZE] = {NULL}; unsigned int i = 0; unsigned int numRelease = 0; LE_TEST_BEGIN_SKIP(!LE_CONFIG_IS_ENABLED(LE_CONFIG_LINUX), 1); #if LE_CONFIG_LINUX // // Spawn child process and perform Assert allocation until failure. // pid_t pID = fork(); if (pID == 0) { // This is the child. // Allocate more than the available objects so the assert will kill the process. for (i = 0; i < ID_POOL_SIZE + 1; i++) { idsPtr[i] = le_mem_AssertAlloc(idPool); } exit(EXIT_SUCCESS); } else { int status; // wait for the child to terminate. wait(&status); LE_TEST_OK(WEXITSTATUS(status) == EXIT_FAILURE, "Assert allocation"); } #endif /* end LE_CONFIG_LINUX */ LE_TEST_END_SKIP(); // // Allocate all objects. // for (i = 0; i < ID_POOL_SIZE; i++) { idsPtr[i] = le_mem_TryAlloc(idPool); LE_TEST_OK(NULL != idsPtr[i], "Allocate id %d", i); if (NULL != idsPtr[i]) { idsPtr[i]->id = i; } } for (i = 0; i < COLOUR_POOL_SIZE; i++) { coloursPtr[i] = le_mem_TryAlloc(colourPool); LE_TEST_OK(NULL != coloursPtr[i], "Allocate color %d", i); if (NULL != idsPtr[i]) { coloursPtr[i]->r = i; coloursPtr[i]->g = i + 1; coloursPtr[i]->b = i + 2; } } // // Check objects // for (i = 0; i < ID_POOL_SIZE; i++) { LE_TEST_OK(idsPtr[i] && (idsPtr[i]->id == i), "Check id %d", i); } for (i = 0; i < COLOUR_POOL_SIZE; i++) { LE_TEST_OK(coloursPtr[i] && ((coloursPtr[i]->r == i) && (coloursPtr[i]->g == i+1) && (coloursPtr[i]->b == i+2)), "Check color %d", i); } // // Randomly release some objects. // { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); //seed the random number generator with the clock srand((unsigned int)(ts.tv_nsec/1000)^ts.tv_sec); idObj_t* objPtr; unsigned int numNotReleased = 0; NumRelease = 0; for (i = 0; i < ID_POOL_SIZE; i++) { objPtr = idsPtr[i]; if (rand() < REMOVE_THRESHOLD) { // Increase the ref number for these objects. le_mem_AddRef(objPtr); // These objects should not get freed. numNotReleased++; } else { idsPtr[i] = NULL; } // Release all objects but only objects that did not have their ref count increased will be released. le_mem_Release(objPtr); } LE_TEST_OK((NumRelease == ID_POOL_SIZE - numNotReleased), "Released %u/%d objects (%u remaining)", NumRelease, ID_POOL_SIZE, numNotReleased); // Release the rest of the objects. for (i = 0; i < ID_POOL_SIZE; i++) { if (idsPtr[i] != NULL) { le_mem_Release(idsPtr[i]); idsPtr[i] = NULL; } } // Check the number of free objects. LE_TEST_BEGIN_SKIP(TEST_MEM_VALGRIND || !LE_CONFIG_IS_ENABLED(LE_CONFIG_MEM_POOL_STATS), 1); le_mem_PoolStats_t stats; le_mem_GetStats(idPool, &stats); LE_TEST_OK((stats.numFree == ID_POOL_SIZE), "Released all objects correctly"); LE_TEST_END_SKIP(); LE_TEST_BEGIN_SKIP(!LE_CONFIG_IS_ENABLED(LE_CONFIG_LINUX), 2); #if LE_CONFIG_LINUX // Spawn child process and try to release an object that is already released. pid_t pID = fork(); if (pID == 0) { // This is the child. // This allocation should fail and kill the process. le_mem_Release(objPtr); exit(EXIT_SUCCESS); } else { int status; // wait for the child to terminate. wait(&status); LE_TEST_OK(( WEXITSTATUS(status) == EXIT_FAILURE ), "Double free terminates process"); // Child terminated with an error. } #endif /* end LE_CONFIG_LINUX */ LE_TEST_END_SKIP(); } // // Try allocate until full. // for (i = 0; i < ID_POOL_SIZE; i++) { if (NULL == idsPtr[i]) { idsPtr[i] = le_mem_TryAlloc(idPool); LE_TEST_OK(NULL != idsPtr[i], "Allocate id %d", i); } } // The pool should now be empty. LE_TEST_BEGIN_SKIP(TEST_MEM_VALGRIND, 1); LE_TEST_OK (le_mem_TryAlloc(idPool) == NULL, "Allocate from empty pool"); LE_TEST_END_SKIP(); // // Force allocate. // le_mem_SetNumObjsToForce(idPool, FORCE_SIZE); for (i = ID_POOL_SIZE; i < ID_POOL_SIZE + NUM_EXTRA_ID; i++) { idsPtr[i] = le_mem_ForceAlloc(idPool); LE_TEST_OK((NULL != idsPtr[i]), "Force alloc id %d", i); } // // Get stats. // le_mem_PoolStats_t stats; LE_TEST_BEGIN_SKIP(TEST_MEM_VALGRIND || !LE_CONFIG_IS_ENABLED(LE_CONFIG_MEM_POOL_STATS), 2); le_mem_GetStats(idPool, &stats); LE_TEST_OK(((stats.numAllocs == ID_POOL_SIZE + NUM_EXTRA_ID + NumRelease) && (stats.numOverflows == (unsigned int)ceil(((1.0*NUM_EXTRA_ID / FORCE_SIZE)))) && (stats.numFree == (stats.numOverflows*FORCE_SIZE) % NUM_EXTRA_ID)), "Check stats"); // // Get pool size. // LE_TEST_OK((le_mem_GetObjectCount(idPool) == ID_POOL_SIZE + (stats.numOverflows * FORCE_SIZE)), "Check pool size"); LE_TEST_END_SKIP(); // // Get object size. // LE_TEST_OK((le_mem_GetObjectSize(idPool) == sizeof(idObj_t)), "Check object size"); // // Reset stats. // LE_TEST_BEGIN_SKIP(TEST_MEM_VALGRIND || !LE_CONFIG_IS_ENABLED(LE_CONFIG_MEM_POOL_STATS), 1); { size_t numFree = stats.numFree; le_mem_ResetStats(idPool); le_mem_GetStats(idPool, &stats); LE_TEST_OK(((stats.numAllocs == 0) && (stats.numOverflows == 0) && (stats.numFree == numFree) ), "Check reset stats"); } LE_TEST_END_SKIP(); // // Create sub-pool. // // Release some objs from the super-pool in a random manner. numRelease = 0; for (i = 0; i < COLOUR_POOL_SIZE; i++) { if (rand() < REMOVE_THRESHOLD) { le_mem_Release(coloursPtr[i]); coloursPtr[i] = NULL; numRelease++; } } // Create the sub-pool. le_mem_PoolRef_t colourSubPool1 = le_mem_CreateSubPool(colourPool, "Colour sub-pool", numRelease); // // Check sub-pools and super-pool. // LE_TEST_OK(NULL != colourSubPool1, "Create sub-pool"); LE_TEST_BEGIN_SKIP(TEST_MEM_VALGRIND, 1); LE_TEST_OK(( (le_mem_GetObjectCount(colourSubPool1) == numRelease) && (le_mem_GetObjectCount(colourPool) == COLOUR_POOL_SIZE) ), "Check sub-pool size"); LE_TEST_END_SKIP(); // // Create second sub-pool. // // Release the rest of the objects from the super-pool. for (i = 0; i < COLOUR_POOL_SIZE; i++) { if (coloursPtr[i] != NULL) { le_mem_Release(coloursPtr[i]); coloursPtr[i] = NULL; } } // Create another sub-pool. le_mem_PoolRef_t colourSubPool2 = le_mem_CreateSubPool(colourPool, "Second sub-pool", COLOUR_POOL_SIZE - numRelease); LE_TEST_OK(NULL != colourSubPool2, "Create second sub-pool"); // // Expand the sub-pool causing the super-pool to expand. // le_mem_ExpandPool(colourSubPool2, NUM_EXPAND_SUB_POOL); // // Allocate from sub-pool. // for (i = 0; i < COLOUR_POOL_SIZE - numRelease; i++) { coloursPtr[i] = le_mem_TryAlloc(colourSubPool2); LE_TEST_OK(NULL != coloursPtr[i], "Allocate color %d from sub-pool", i); } // // Check pools. // LE_TEST_BEGIN_SKIP(TEST_MEM_VALGRIND || !LE_CONFIG_IS_ENABLED(LE_CONFIG_MEM_POOL_STATS), 4); le_mem_GetStats(colourPool, &stats); LE_TEST_OK(( (le_mem_GetObjectCount(colourPool) == COLOUR_POOL_SIZE + NUM_EXPAND_SUB_POOL) && (stats.numFree == 0) ), "Check super-pool stats"); le_mem_GetStats(colourSubPool1, &stats); LE_TEST_OK(( (le_mem_GetObjectCount(colourSubPool1) == numRelease) && (stats.numFree == numRelease) ), "Check sub-pool stats"); le_mem_GetStats(colourSubPool2, &stats); LE_TEST_OK(( (le_mem_GetObjectCount(colourSubPool2) == COLOUR_POOL_SIZE - numRelease + NUM_EXPAND_SUB_POOL) && (stats.numFree == NUM_EXPAND_SUB_POOL) ), "Check second sub-pool stats"); // Try Allocating from empty super-pool. LE_TEST_OK(le_mem_TryAlloc(colourPool) == NULL, "Allocate from empty super-pool"); LE_TEST_END_SKIP(); // // Delete sub-pool. // le_mem_DeleteSubPool(colourSubPool1); // Allocate from the super-pool. for (i = 0; i < NUM_ALLOC_SUPER_POOL; i++) { if (COLOUR_POOL_SIZE > numRelease) { coloursPtr[numRelease] = le_mem_TryAlloc(colourPool); LE_TEST_OK(NULL != coloursPtr[numRelease], "Allocate item %d from super-pool", numRelease); } } // // Check pools. // LE_TEST_BEGIN_SKIP(TEST_MEM_VALGRIND || !LE_CONFIG_IS_ENABLED(LE_CONFIG_MEM_POOL_STATS), 3); le_mem_GetStats(colourPool, &stats); LE_TEST_OK((stats.numFree == numRelease - NUM_ALLOC_SUPER_POOL), "checking super-pool stats after releasing sub-pool"); le_mem_GetStats(colourSubPool2, &stats); LE_TEST_OK(( (le_mem_GetObjectCount(colourSubPool2) == COLOUR_POOL_SIZE - numRelease + NUM_EXPAND_SUB_POOL) && (stats.numFree == NUM_EXPAND_SUB_POOL) ), "checking second sub-pool stats after releasing sub-pool"); // // Re-create sub-pool causing super pool to expand. // colourSubPool1 = le_mem_CreateSubPool(colourPool, "First sub-pool", numRelease + NUM_EXPAND_SUB_POOL); LE_TEST_OK(((le_mem_GetObjectCount(colourSubPool1) == numRelease + NUM_EXPAND_SUB_POOL) && (le_mem_GetObjectCount(colourPool) == COLOUR_POOL_SIZE + 2*NUM_EXPAND_SUB_POOL + NUM_ALLOC_SUPER_POOL)), "recreated sub-pool"); LE_TEST_END_SKIP(); // Create some reduced sub-pools le_mem_PoolRef_t tieredStrPoolMed = le_mem_CreateReducedPool(stringPool, "stringPoolMed", 0, STRING_POOL_MED_BYTES); le_mem_PoolRef_t tieredStrPoolSmall = le_mem_CreateReducedPool(tieredStrPoolMed, "stringPoolSmall", 4, STRING_POOL_SMALL_BYTES); size_t medObjectSize = le_mem_GetObjectSize(tieredStrPoolMed); size_t smallObjectSize = le_mem_GetObjectSize(tieredStrPoolSmall); LE_TEST_OK(STRING_POOL_MED_BYTES <= medObjectSize && medObjectSize < STRING_POOL_BYTES/2, "Check medium pool size (%"PRIuS") is reasonable", medObjectSize); LE_TEST_OK(STRING_POOL_SMALL_BYTES <= smallObjectSize && smallObjectSize < medObjectSize/2, "Check small pool size (%"PRIuS") is reasonable", smallObjectSize); // Try allocating random sized strings int points = STRING_POOL_SIZE*4; for (i = 0; i < 4*STRING_POOL_SIZE && points >= 4; i++) { // Always allocate at least one byte size_t allocSize = (rand() % (STRING_POOL_BYTES-1)) + 1; stringsPtr[i] = le_mem_ForceVarAlloc(tieredStrPoolSmall, allocSize); LE_TEST_OK(stringsPtr[i], "allocate buffer %d (size %"PRIuS")", i, allocSize); memset(stringsPtr[i], 'a', allocSize); if (allocSize <= smallObjectSize) { points -= 1; LE_TEST_OK(le_mem_GetBlockSize(stringsPtr[i]) == smallObjectSize, "got a small object"); } else if (allocSize <= medObjectSize) { points -= 2; LE_TEST_OK(le_mem_GetBlockSize(stringsPtr[i]) == medObjectSize, "got a medium object"); } else { points -= 4; LE_TEST_OK(le_mem_GetBlockSize(stringsPtr[i]) == STRING_POOL_BYTES, "got a large object"); } } // Now try hibernating -- first disable interrupts LE_TEST_BEGIN_SKIP(!LE_CONFIG_IS_ENABLED(LE_CONFIG_RTOS), 3); #if LE_CONFIG_RTOS taskENTER_CRITICAL(); void *beginFree, *endFree; le_mem_Hibernate(&beginFree, &endFree); LE_TEST_OK(endFree - beginFree > 0, "Free %" PRIuS " bytes of memory by hibernating", endFree - beginFree); le_mem_Resume(); taskEXIT_CRITICAL(); #endif /* end LE_CONFIG_RTOS */ LE_TEST_END_SKIP(); // Now finish up by allocating some small strings for(; i < 4*STRING_POOL_SIZE && points >= 0; ++i) { stringsPtr[i] = le_mem_ForceVarAlloc(tieredStrPoolSmall, 1); LE_TEST_OK(stringsPtr[i], "allocate buffer %d (size 1)", i); memset(stringsPtr[i], 'b', 1); LE_TEST_OK(le_mem_GetBlockSize(stringsPtr[i]) == smallObjectSize, "got a small object"); points -= 1; } LE_TEST_INFO("Releasing some buffers"); for (i = 0; i < 4*STRING_POOL_SIZE && stringsPtr[i]; i++) { if (rand() < REMOVE_THRESHOLD) { le_mem_Release(stringsPtr[i]); stringsPtr[i] = NULL; numRelease++; } } LE_TEST_INFO("Re-allocate as small buffers"); for (; i-- > 0; ) { if (!stringsPtr[i]) { stringsPtr[i] = le_mem_ForceVarAlloc(tieredStrPoolSmall, 1); LE_TEST_OK(stringsPtr[i], "allocated a small buffer"); memset(stringsPtr[i], 'c', 1); } } LE_TEST_INFO("Free everything"); for (i = 0; i < 4*STRING_POOL_SIZE && stringsPtr[i]; ++i) { le_mem_Release(stringsPtr[i]); stringsPtr[i] = NULL; } // And delete the sub-pools LE_TEST_INFO("Delete sub-pools"); le_mem_DeleteSubPool(tieredStrPoolSmall); le_mem_DeleteSubPool(tieredStrPoolMed); }
int main(int argc, char *argv[]) { le_mem_PoolRef_t idPool, colourPool; idObj_t* idsPtr[ID_POOL_SIZE + NUM_EXTRA_ID] = {NULL}; colourObj_t* coloursPtr[COLOUR_POOL_SIZE] = {NULL}; unsigned int i = 0; unsigned int numRelease = 0; printf("\n"); printf("*** Unit Test for le_mem module. ***\n"); // // Create multiple pools. // idPool = le_mem_CreatePool("ID Pool", sizeof(idObj_t)); colourPool = le_mem_CreatePool("Colour Pool", sizeof(colourObj_t)); printf("Created two memory pools.\n"); // // Expand the pools. // idPool = le_mem_ExpandPool(idPool, ID_POOL_SIZE); colourPool = le_mem_ExpandPool(colourPool, COLOUR_POOL_SIZE); printf("Expanded all pools.\n"); // // Set destructors. // le_mem_SetDestructor(idPool, IdDestructor); // // Spawn child process and perform Assert allocation until failure. // pid_t pID = fork(); if (pID == 0) { // This is the child. // Allocate more than the available objects so the assert will kill the process. for (i = 0; i < ID_POOL_SIZE + 1; i++) { idsPtr[i] = le_mem_AssertAlloc(idPool); } return LE_OK; } else { int status; // wait for the child to terminate. wait(&status); if ( WEXITSTATUS(status) == EXIT_FAILURE ) // Child terminated with an error. { printf("Assert allocation performed correctly.\n"); } else { printf("Assert allocation incorrect: %d", __LINE__); return LE_FAULT; } } // // Allocate all objects. // for (i = 0; i < ID_POOL_SIZE; i++) { idsPtr[i] = le_mem_TryAlloc(idPool); if (idsPtr[i] == NULL) { printf("Allocation error: %d", __LINE__); return LE_FAULT; } idsPtr[i]->id = i; } for (i = 0; i < COLOUR_POOL_SIZE; i++) { coloursPtr[i] = le_mem_TryAlloc(colourPool); if (coloursPtr[i] == NULL) { printf("Allocation error: %d", __LINE__); return LE_FAULT; } coloursPtr[i]->r = i; coloursPtr[i]->g = i + 1; coloursPtr[i]->b = i + 2; } printf("Allocated all objects from all pools.\n"); // // Check objects // for (i = 0; i < ID_POOL_SIZE; i++) { if (idsPtr[i]->id != i) { printf("Object error: %d", __LINE__); return LE_FAULT; } } for (i = 0; i < COLOUR_POOL_SIZE; i++) { if ( (coloursPtr[i]->r != i) || (coloursPtr[i]->g != i+1) || (coloursPtr[i]->b != i+2) ) { printf("Object error: %d", __LINE__); return LE_FAULT; } } printf("Checked all objects in pools.\n"); // // Randomly release some objects. // { //seed the random number generator with the clock srand((unsigned int)clock()); idObj_t* objPtr; size_t numNotReleased = 0; NumRelease = 0; for (i = 0; i < ID_POOL_SIZE; i++) { objPtr = idsPtr[i]; if (rand() < REMOVE_THRESHOLD) { // Increase the ref number for these objects. le_mem_AddRef(objPtr); // These objects should not get freed. numNotReleased++; } else { idsPtr[i] = NULL; } // Release all objects but only objects that did not have their ref count increased will be released. le_mem_Release(objPtr); } if (NumRelease != ID_POOL_SIZE - numNotReleased) { printf("Released objects incorrectly: %d", __LINE__); return LE_FAULT; } // Release the rest of the objects. for (i = 0; i < ID_POOL_SIZE; i++) { if (idsPtr[i] != NULL) { le_mem_Release(idsPtr[i]); idsPtr[i] = NULL; } } // Check the number of free objects. le_mem_PoolStats_t stats; le_mem_GetStats(idPool, &stats); if (stats.numFree != ID_POOL_SIZE) { printf("Released objects incorrectly: %d", __LINE__); return LE_FAULT; } // Spawn child process and try to release an object that is already released. pid_t pID = fork(); if (pID == 0) { // This is the child. // This allocation should fail and kill the process. le_mem_Release(objPtr); return LE_OK; } else { int status; // wait for the child to terminate. wait(&status); if ( WEXITSTATUS(status) == EXIT_FAILURE ) // Child terminated with an error. { printf("Ref count correct.\n"); } else { printf("Ref count incorrect: %d", __LINE__); return LE_FAULT; } } } printf("Released objects according to ref counts correctly.\n"); printf("Checked that destructors were called correctly.\n"); // // Try allocate until full. // for (i = 0; i < ID_POOL_SIZE; i++) { if (idsPtr[i] == NULL) { idsPtr[i] = le_mem_TryAlloc(idPool); if (idsPtr[i] == NULL) { printf("Allocation error: %d.", __LINE__); return LE_FAULT; } } } // The pool should now be empty. if (le_mem_TryAlloc(idPool) != NULL) { printf("Allocation error: %d.", __LINE__); return LE_FAULT; } printf("Tried allocating from empty pool.\n"); // // Force allocate. // le_mem_SetNumObjsToForce(idPool, FORCE_SIZE); for (i = ID_POOL_SIZE; i < ID_POOL_SIZE + NUM_EXTRA_ID; i++) { idsPtr[i] = le_mem_ForceAlloc(idPool); if (idsPtr[i] == NULL) { printf("Allocation error: %d.", __LINE__); return LE_FAULT; } } printf("Forced allocated objects.\n"); // // Get stats. // le_mem_PoolStats_t stats; le_mem_GetStats(idPool, &stats); if ( (stats.numAllocs != ID_POOL_SIZE + NUM_EXTRA_ID + NumRelease) || (stats.numOverflows != (unsigned int)ceil(((1.0*NUM_EXTRA_ID / FORCE_SIZE)))) || (stats.numFree != (stats.numOverflows*FORCE_SIZE) % NUM_EXTRA_ID) ) { printf("Stats are incorrect: %d", __LINE__); return LE_FAULT; } printf("Stats are correct.\n"); // // Get pool size. // if (le_mem_GetTotalNumObjs(idPool) != ID_POOL_SIZE + (stats.numOverflows * FORCE_SIZE)) { printf("Pool size incorrect: %d", __LINE__); return LE_FAULT; } printf("Checked pool size.\n"); // // Get object size. // if (le_mem_GetObjectSize(idPool) != sizeof(idObj_t)) { printf("Object size incorrect: %d", __LINE__); return LE_FAULT; } printf("Checked object size.\n"); // // Reset stats. // { size_t numFree = stats.numFree; le_mem_ResetStats(idPool); le_mem_GetStats(idPool, &stats); if ( (stats.numAllocs != 0) || (stats.numOverflows != 0) || (stats.numFree != numFree) ) { printf("Stats are incorrect: %d", __LINE__); return LE_FAULT; } } printf("Reset stats correctly.\n"); // // Create sub-pool. // // Release some objs from the super-pool in a random manner. numRelease = 0; for (i = 0; i < COLOUR_POOL_SIZE; i++) { if (rand() < REMOVE_THRESHOLD) { le_mem_Release(coloursPtr[i]); coloursPtr[i] = NULL; numRelease++; } } // Create the sub-pool. le_mem_PoolRef_t colourSubPool1 = le_mem_CreateSubPool(colourPool, "Colour sub-pool", numRelease); // // Check sub-pools and super-pool. // if ( (le_mem_GetTotalNumObjs(colourSubPool1) != numRelease) || (le_mem_GetTotalNumObjs(colourPool) != COLOUR_POOL_SIZE) ) { printf("Sub-pool incorrect: %d", __LINE__); return LE_FAULT; } printf("Sub-pool created correctly.\n"); // // Create second sub-pool. // // Release the rest of the objects from the super-pool. for (i = 0; i < COLOUR_POOL_SIZE; i++) { if (coloursPtr[i] != NULL) { le_mem_Release(coloursPtr[i]); coloursPtr[i] = NULL; } } // Create another sub-pool. le_mem_PoolRef_t colourSubPool2 = le_mem_CreateSubPool(colourPool, "Second sub-pool", COLOUR_POOL_SIZE - numRelease); printf("Created second sub-pool.\n"); // // Expand the sub-pool causing the super-pool to expand. // le_mem_ExpandPool(colourSubPool2, NUM_EXPAND_SUB_POOL); // // Allocate from sub-pool. // for (i = 0; i < COLOUR_POOL_SIZE - numRelease; i++) { coloursPtr[i] = le_mem_TryAlloc(colourSubPool2); if (coloursPtr[i] == NULL) { printf("Error allocating from sub-pool: %d", __LINE__); return LE_FAULT; } } // // Check pools. // le_mem_GetStats(colourPool, &stats); if ( (le_mem_GetTotalNumObjs(colourPool) != COLOUR_POOL_SIZE + NUM_EXPAND_SUB_POOL) || (stats.numFree != 0) ) { printf("Error in super-pool: %d", __LINE__); return LE_FAULT; } le_mem_GetStats(colourSubPool1, &stats); if ( (le_mem_GetTotalNumObjs(colourSubPool1) != numRelease) || (stats.numFree != numRelease) ) { printf("Error in sub-pool: %d", __LINE__); return LE_FAULT; } le_mem_GetStats(colourSubPool2, &stats); if ( (le_mem_GetTotalNumObjs(colourSubPool2) != COLOUR_POOL_SIZE - numRelease + NUM_EXPAND_SUB_POOL) || (stats.numFree != NUM_EXPAND_SUB_POOL) ) { printf("Error in sub-pool: %d", __LINE__); return LE_FAULT; } printf("Expanded sub-pool correctly.\n"); printf("Allocated from sub-pools correctly.\n"); // Try Allocating from empty super-pool. if (le_mem_TryAlloc(colourPool) != NULL) { printf("Error in super-pool: %d", __LINE__); return LE_FAULT; } // // Delete sub-pool. // le_mem_DeleteSubPool(colourSubPool1); // Allocate from the super-pool. for (i = 0; i < NUM_ALLOC_SUPER_POOL; i++) { coloursPtr[numRelease] = le_mem_AssertAlloc(colourPool); } // // Check pools. // le_mem_GetStats(colourPool, &stats); if ( (stats.numFree != numRelease - NUM_ALLOC_SUPER_POOL) ) { printf("Error in super-pool: %d", __LINE__); return LE_FAULT; } le_mem_GetStats(colourSubPool2, &stats); if ( (le_mem_GetTotalNumObjs(colourSubPool2) != COLOUR_POOL_SIZE - numRelease + NUM_EXPAND_SUB_POOL) || (stats.numFree != NUM_EXPAND_SUB_POOL) ) { printf("Error in sub-pool: %d", __LINE__); return LE_FAULT; } printf("Deleted sub-pool correctly.\n"); // // Re-create sub-pool causing super pool to expand. // colourSubPool1 = le_mem_CreateSubPool(colourPool, "First sub-pool", numRelease + NUM_EXPAND_SUB_POOL); if ( (le_mem_GetTotalNumObjs(colourSubPool1) != numRelease + NUM_EXPAND_SUB_POOL) || (le_mem_GetTotalNumObjs(colourPool) != COLOUR_POOL_SIZE + 2*NUM_EXPAND_SUB_POOL + NUM_ALLOC_SUPER_POOL) ) { printf("Error re-creating sub-pool: %d", __LINE__); return LE_FAULT; } printf("Successfully recreated sub-pool.\n"); // // Search for pools by name. // if ( (idPool != le_mem_FindPool("ID Pool")) || (colourSubPool1 != le_mem_FindPool("First sub-pool")) ) { printf("Error finding pools by name: %d", __LINE__); return LE_FAULT; } printf("Successfully searched for pools by name.\n"); printf("*** Unit Test for le_mem module passed. ***\n"); printf("\n"); return LE_OK; }