Example #1
0
//--------------------------------------------------------------------------------------------------
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;
}
Example #2
0
//--------------------------------------------------------------------------------------------------
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));
    }
}
Example #3
0
//--------------------------------------------------------------------------------------------------
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);
}
Example #4
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;
}
Example #5
0
// -------------------------------------------------------------------------------------------------
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);
}
Example #6
0
//--------------------------------------------------------------------------------------------------
void atmachinestring_Init
(
    void
)
{
    AtStringPool = le_mem_CreatePool("AtStringPool",sizeof(atmachinestring_t));
    le_mem_ExpandPool(AtStringPool,DEFAULT_ATSTRING_POOL_SIZE);
}
Example #7
0
//--------------------------------------------------------------------------------------------------
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);
}
Example #8
0
//--------------------------------------------------------------------------------------------------
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);
}
Example #9
0
//--------------------------------------------------------------------------------------------------
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);
}
Example #10
0
//--------------------------------------------------------------------------------------------------
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);
}
Example #11
0
//--------------------------------------------------------------------------------------------------
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");
}
Example #12
0
//--------------------------------------------------------------------------------------------------
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;
}
Example #13
0
//--------------------------------------------------------------------------------------------------
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;
}
Example #14
0
//--------------------------------------------------------------------------------------------------
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);
}
Example #15
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);
    }
}
Example #16
0
// -------------------------------------------------------------------------------------------------
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);
}
Example #17
0
//--------------------------------------------------------------------------------------------------
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;
}
Example #18
0
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);
}
Example #19
0
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;
}