//-------------------------------------------------------------------------------------------------- static dstr_Ref_t NewOrFirstSegmentRef ( dstr_Ref_t headRef ///< [IN] The head of the string. ) //-------------------------------------------------------------------------------------------------- { dstr_Ref_t segmentRef = FirstSegmentRef(headRef); if (segmentRef != NULL) { return segmentRef; } segmentRef = NewSegment(); le_sls_Stack(&headRef->head.list, &segmentRef->body.link); return segmentRef; }
//-------------------------------------------------------------------------------------------------- static void AddDestructor ( ThreadObj_t* threadPtr, ///< [in] Ptr to the Thread Object to add the destructor to. le_thread_Destructor_t destructor, ///< [in] The function to be called. void* context ///< [in] Parameter to pass to the destructor function. ) { // Create the destructor object. DestructorObj_t* destructorObjPtr = le_mem_ForceAlloc(DestructorObjPool); // Init the destructor object. destructorObjPtr->destructor = destructor; destructorObjPtr->context = context; destructorObjPtr->link = LE_SLS_LINK_INIT; // Get a pointer to the calling thread's Thread Object and // Add the destructor object to its list. le_sls_Stack(&(threadPtr->destructorList), &(destructorObjPtr->link)); }
//-------------------------------------------------------------------------------------------------- static void InitBlock ( le_mem_PoolRef_t pool, ///< [IN] The pool the new block belongs to. MemBlock_t* newBlockPtr ///< [IN] The block being initialized. ) { // Initialize the block. #ifndef LE_MEM_VALGRIND // Add the block to the pool's free list. newBlockPtr->link = LE_SLS_LINK_INIT; le_sls_Stack(&(pool->freeList), &(newBlockPtr->link)); #endif newBlockPtr->refCount = 0; newBlockPtr->poolPtr = pool; #ifdef USE_GUARD_BAND InitGuardBands(newBlockPtr); #endif }
//-------------------------------------------------------------------------------------------------- static void PushContext ( Parser_t* parserPtr, le_json_ContextType_t type, le_json_EventHandler_t eventHandler ) //-------------------------------------------------------------------------------------------------- { Context_t* contextPtr = le_mem_ForceAlloc(ContextPool); contextPtr->link = LE_SLS_LINK_INIT; contextPtr->type = type; contextPtr->eventHandler = eventHandler; le_sls_Stack(&parserPtr->contextStack, &contextPtr->link); // Clear the value buffer. memset(parserPtr->buffer, 0, sizeof(parserPtr->buffer)); parserPtr->numBytes = 0; }
//-------------------------------------------------------------------------------------------------- static void MoveBlocks ( le_mem_PoolRef_t destPool, ///< [IN] The pool to move the blocks to. le_mem_PoolRef_t srcPool, ///< [IN] The pool to get the blocks from. size_t numBlocks ///< [IN] The maximum number of blocks to move. ) { #ifndef LE_MEM_VALGRIND // Get the first block to move. le_sls_Link_t* blockLinkPtr = le_sls_Pop(&(srcPool->freeList)); size_t i = 0; while (i < numBlocks) { if (blockLinkPtr == NULL) { LE_FATAL("Asked to move %zu blocks from pool '%s' to pool '%s', " "but only %zu were available.", numBlocks, srcPool->name, destPool->name, i); } // Add the block to the destination pool. le_sls_Stack(&(destPool->freeList), blockLinkPtr); // Update the blocks parent pool. MemBlock_t* blockPtr = CONTAINER_OF(blockLinkPtr, MemBlock_t, link); blockPtr->poolPtr = destPool; // Get the next block. blockLinkPtr = le_sls_Pop(&(srcPool->freeList)); i++; } #endif }
//-------------------------------------------------------------------------------------------------- void le_mem_Release ( void* objPtr ///< [IN] Pointer to the object to be released. ) { MemBlock_t* blockPtr; // Get the block from the object pointer. #ifdef USE_GUARD_BAND uint8_t* dataPtr = objPtr; dataPtr -= GUARD_BAND_SIZE; blockPtr = CONTAINER_OF(dataPtr, MemBlock_t, data); #else blockPtr = CONTAINER_OF(objPtr, MemBlock_t, data); #endif #ifdef USE_GUARD_BAND CheckGuardBands(blockPtr); #endif Lock(); switch (blockPtr->refCount) { case 1: { MemPool_t* poolPtr = blockPtr->poolPtr; // The reference count has reached zero. blockPtr->refCount = 0; // Call the destructor, if there is one. if (poolPtr->destructor) { // Make sure that the destructor is not called with the mutex locked, because // it is not a recursive mutex and therefore will deadlock if locked again by // the same thread. Also, fetch the destructor function address before unlocking // the mutex so that we don't touch the pool object while the mutex is unlocked. le_mem_Destructor_t destructor = poolPtr->destructor; Unlock(); destructor(objPtr); // Re-lock the mutex now so that it is safe to access the pool object again. Lock(); } #ifndef LE_MEM_VALGRIND // Release the memory back into the pool. // Note that we don't do this before calling the destructor because the destructor // still needs to access it, but after it goes back on the free list, it could get // reallocated by another thread (or even the destructor itself) and have its // contents clobbered. le_sls_Stack(&(poolPtr->freeList), &(blockPtr->link)); #else free(blockPtr); #endif poolPtr->numBlocksInUse--; break; } case 0: LE_EMERG("Releasing free block."); LE_FATAL("Free block released from pool %p (%s).", blockPtr->poolPtr, blockPtr->poolPtr->name); default: blockPtr->refCount--; } Unlock(); }
static le_result_t TestSinglyLinkLists(size_t maxListSize) { // Node definition. typedef struct { le_sls_Link_t link; uint32_t id; } idRecord_t; int i; le_sls_List_t list0, list1; printf("\n"); printf("*** Unit Test for le_singlyLinkedList module. ***\n"); // // Multiple list creation // // Initialize the lists list0 = LE_SLS_LIST_INIT; list1 = LE_SLS_LIST_INIT; printf("One singly linked list was successfully created.\n"); // // Attempt to query empty list // if ( (le_sls_Peek(&list0) != NULL) || (le_sls_Pop(&list0) != NULL) ) { printf("Query of empty list failed: %d", __LINE__); return LE_FAULT; } printf("Query of empty list correct.\n"); // // Node insertions // { idRecord_t* newNodePtr; le_sls_Link_t* prevLinkPtr; // Queue nodes to list0. for (i = 0; i < maxListSize; i++) { // Create the new node newNodePtr = (idRecord_t*)malloc(sizeof(idRecord_t)); newNodePtr->id = i; // Initialize the link. newNodePtr->link = LE_SLS_LINK_INIT; if (i < maxListSize/2) { // Insert the new node to the tail. le_sls_Queue(&list0, &(newNodePtr->link)); } else { // Insert to the tail using insert after. le_sls_AddAfter(&list0, prevLinkPtr, &(newNodePtr->link)); } prevLinkPtr = &(newNodePtr->link); } printf("%zu nodes were queued to the tail of list0.\n", maxListSize); // Stack nodes to list1. for (i = 0; i < maxListSize; i++) { // Create the new node newNodePtr = (idRecord_t*)malloc(sizeof(idRecord_t)); newNodePtr->id = i; // Initialize the link. newNodePtr->link = LE_SLS_LINK_INIT; // Insert the new node to the head. le_sls_Stack(&list1, &(newNodePtr->link)); } printf("%zu nodes were stacked to the head of list1.\n", maxListSize); } // // Check that all the nodes have been added properly // { idRecord_t* nodePtr; le_sls_Link_t* link0Ptr = le_sls_Peek(&list0); le_sls_Link_t* link1Ptr = le_sls_Peek(&list1); if ( (link0Ptr == NULL) || (link1Ptr == NULL) ) { printf("Link error: %d", __LINE__); return LE_FAULT; } i = 0; do { // Get the node from list 0 nodePtr = CONTAINER_OF(link0Ptr, idRecord_t, link); // Check the node. if ( nodePtr->id != i) { printf("Link error: %d", __LINE__); return LE_FAULT; } // Get the node from list 1 nodePtr = CONTAINER_OF(link1Ptr, idRecord_t, link); // Check the node. if ( nodePtr->id != maxListSize - i - 1) { printf("Link error: %d", __LINE__); return LE_FAULT; } // Move to the next node. link0Ptr = le_sls_PeekNext(&list0, link0Ptr); link1Ptr = le_sls_PeekNext(&list1, link1Ptr); i++; } while (link0Ptr != NULL); // Make sure everything is correct. if ( (i != maxListSize) || (link1Ptr != NULL) ) { printf("Link error: %d", __LINE__); return LE_FAULT; } } printf("Checked that all nodes added to the head and tails are all correct.\n"); // // Pop nodes. // { //pop half the list. for (i = 0; i < (maxListSize / 2); i++) { le_sls_Pop(&list0); } } printf("Popped half the nodes from the head of list0.\n"); // Check that the list is still in tact. { idRecord_t* nodePtr; // For list 0. le_sls_Link_t* linkPtr = le_sls_Peek(&list0); i = maxListSize/2; do { nodePtr = CONTAINER_OF(linkPtr, idRecord_t, link); if (nodePtr->id != i++) { printf("Link error: %d", __LINE__); return LE_FAULT; } linkPtr = le_sls_PeekNext(&list0, linkPtr); } while (linkPtr != NULL); // Check that the number of links left is correct. if (i != maxListSize) { printf("Wrong number of links: %d", __LINE__); return LE_FAULT; } } printf("Checked that all nodes were properly popped from the lists.\n"); // // Check for list corruption. // { le_sls_Link_t* linkPtr; if (le_sls_IsListCorrupted(&list0)) { printf("List0 is corrupt but shouldn't be: %d", __LINE__); return LE_FAULT; } // Access one of the links directly. This should corrupt the list. linkPtr = le_sls_Peek(&list0); linkPtr = le_sls_PeekNext(&list0, linkPtr); linkPtr->nextPtr = NULL; if (!le_sls_IsListCorrupted(&list0)) { printf("List0 is not corrupted but should be: %d", __LINE__); return LE_FAULT; } } printf("Checked lists for corruption.\n"); printf("*** Unit Test for le_singlyLinkedList module passed. ***\n"); printf("\n"); return LE_OK; }