/* * Copyright 2018-2020 NXP * All rights reserved. * * * SPDX-License-Identifier: BSD-3-Clause */ #include "fsl_common.h" #if defined(MEM_STATISTICS_INTERNAL) || defined(MEM_MANAGER_BENCH) #include "fsl_component_timer_manager.h" #include "fsl_component_mem_manager_internal.h" #endif /* MEM_STATISTICS_INTERNAL MEM_MANAGER_BENCH*/ #include "fsl_component_mem_manager.h" #if (defined(MEM_MANAGER_ENABLE_TRACE) && (MEM_MANAGER_ENABLE_TRACE > 0U)) #include "fsl_debug_console.h" #endif #if defined(OSA_USED) #include "fsl_os_abstraction.h" #if (defined(USE_RTOS) && (USE_RTOS > 0U)) #define MEM_ENTER_CRITICAL() \ OSA_SR_ALLOC(); \ OSA_ENTER_CRITICAL() #define MEM_EXIT_CRITICAL() OSA_EXIT_CRITICAL() #else #define MEM_ENTER_CRITICAL() #define MEM_EXIT_CRITICAL() #endif #else #define MEM_ENTER_CRITICAL() uint32_t regPrimask = DisableGlobalIRQ(); #define MEM_EXIT_CRITICAL() EnableGlobalIRQ(regPrimask); #endif #if !defined(gMemManagerLight) || (gMemManagerLight == 0) /***************************************************************************** ****************************************************************************** * Private macros ****************************************************************************** *****************************************************************************/ #if defined(__IAR_SYSTEMS_ICC__) #define __mem_get_LR() __get_LR() #elif defined(__GNUC__) #define __mem_get_LR() __builtin_return_address(0) #elif defined(__CC_ARM) || defined(__ARMCC_VERSION) #define __mem_get_LR() __return_address() #endif #if (defined(MEM_MANAGER_PRE_CONFIGURE) && (MEM_MANAGER_PRE_CONFIGURE > 0U)) #undef _block_set_ #undef _eol_ #define _eol_ ; #define _block_set_ MEM_BLOCK_BUFFER_NONAME_DEFINE PoolsDetails_c #undef _block_set_ #undef _number_of_blocks_ #undef _eol_ #undef _pool_id_ #define _eol_ , #define _block_set_ MEM_BLOCK_NONAME_BUFFER static uint8_t const *s_PoolList[] = {PoolsDetails_c}; #endif /*MEM_MANAGER_PRE_CONFIGURE*/ /***************************************************************************** ****************************************************************************** * Private type definitions ****************************************************************************** *****************************************************************************/ /*! @brief Buffer pools structure*/ typedef struct _mem_pool_structure { struct _mem_pool_structure *nextPool; uint8_t *pHeap; uint32_t heapSize; #if (defined(MEM_MANAGER_ENABLE_TRACE) && (MEM_MANAGER_ENABLE_TRACE > 0U)) uint16_t allocatedBlocksPeak; uint16_t poolFragmentWaste; uint16_t poolTotalFragmentWaste; uint16_t poolFragmentWastePeak; uint16_t poolFragmentMinWaste; #endif /*MEM_MANAGER_ENABLE_TRACE*/ uint16_t poolId; uint16_t blockSize; uint16_t numBlocks; uint16_t allocatedBlocks; } mem_pool_structure_t; /*! @brief Header description for buffers.*/ typedef struct _block_list_header { uint16_t allocated; uint16_t blockSize; #if (defined(MEM_MANAGER_ENABLE_TRACE) && (MEM_MANAGER_ENABLE_TRACE > 0U)) uint32_t caller; uint16_t allocatedBytes; #endif /*MEM_MANAGER_ENABLE_TRACE*/ } block_list_header_t; /*! @brief State structure for memory manager. */ typedef struct _mem_manager_info { mem_pool_structure_t *pHeadPool; uint16_t poolNum; #if (defined(MEM_MANAGER_ENABLE_TRACE) && (MEM_MANAGER_ENABLE_TRACE > 0U)) uint16_t allocationFailures; uint16_t freeFailures; #endif /*MEM_MANAGER_ENABLE_TRACE*/ } mem_manager_info_t; /***************************************************************************** ****************************************************************************** * Public memory declarations ****************************************************************************** *****************************************************************************/ /***************************************************************************** ***************************************************************************** * Private prototypes ***************************************************************************** *****************************************************************************/ /***************************************************************************** ***************************************************************************** * Private memory definitions ***************************************************************************** *****************************************************************************/ static mem_manager_info_t s_memmanager = {0}; #ifdef MEM_STATISTICS_INTERNAL static mem_statis_t s_memStatis; #endif /* MEM_STATISTICS_INTERNAL */ /***************************************************************************** ****************************************************************************** * Private API macro define ****************************************************************************** *****************************************************************************/ #define BLOCK_HDR_SIZE sizeof(block_list_header_t) /***************************************************************************** ****************************************************************************** * Private functions ****************************************************************************** *****************************************************************************/ #ifdef MEM_STATISTICS_INTERNAL static void MEM_BufferAllocates_memStatis(void *buffer, uint32_t time, uint32_t requestedSize) { block_list_header_t *pBlock = (block_list_header_t *)buffer - 1; /* existing block must have a BlockHdr and a next BlockHdr */ assert((pBlock != NULL)); s_memStatis.nb_alloc++; /* Sort the buffers by size, based on defined thresholds */ if (requestedSize <= SMALL_BUFFER_SIZE) { s_memStatis.nb_small_buffer++; UPDATE_PEAK(s_memStatis.nb_small_buffer, s_memStatis.peak_small_buffer); } else if (requestedSize <= LARGE_BUFFER_SIZE) { s_memStatis.nb_medium_buffer++; UPDATE_PEAK(s_memStatis.nb_medium_buffer, s_memStatis.peak_medium_buffer); } else { s_memStatis.nb_large_buffer++; UPDATE_PEAK(s_memStatis.nb_large_buffer, s_memStatis.peak_large_buffer); } /* the RAM allocated is the buffer size and the block header size*/ s_memStatis.ram_allocated += (uint16_t)(requestedSize + BLOCK_HDR_SIZE); UPDATE_PEAK(s_memStatis.ram_allocated, s_memStatis.peak_ram_allocated); uint32_t block_size = 0U; block_size = pBlock->blockSize; assert(block_size >= requestedSize); /* ram lost is the difference between block size and buffer size */ s_memStatis.ram_lost += (uint16_t)(block_size - requestedSize); UPDATE_PEAK(s_memStatis.ram_lost, s_memStatis.peak_ram_lost); /* UPDATE_PEAK(((uint32_t)FreeBlockHdrList.tail + BLOCK_HDR_SIZE), s_memStatis.peak_upper_addr); */ #ifdef MEM_MANAGER_BENCH if (time != 0U) { /* update mem stats used for benchmarking */ s_memStatis.last_alloc_block_size = (uint16_t)block_size; s_memStatis.last_alloc_buff_size = (uint16_t)requestedSize; s_memStatis.last_alloc_time = (uint16_t)time; s_memStatis.total_alloc_time += time; s_memStatis.average_alloc_time = (uint16_t)(s_memStatis.total_alloc_time / s_memStatis.nb_alloc); UPDATE_PEAK((uint16_t)time, s_memStatis.peak_alloc_time); } else /* alloc time is not correct, we bypass this allocation's data */ { s_memStatis.nb_alloc--; } #else NOT_USED(time); #endif /* MEM_MANAGER_BENCH */ } static void MEM_BufferFrees_memStatis(void *buffer) { block_list_header_t *pBlock = (block_list_header_t *)buffer - 1; s_memStatis.ram_allocated -= (uint16_t)(pBlock->allocatedBytes + BLOCK_HDR_SIZE); /* Sort the buffers by size, based on defined thresholds */ if (pBlock->allocatedBytes <= SMALL_BUFFER_SIZE) { s_memStatis.nb_small_buffer--; } else if (pBlock->allocatedBytes <= LARGE_BUFFER_SIZE) { s_memStatis.nb_medium_buffer--; } else { s_memStatis.nb_large_buffer--; } uint16_t block_size = 0U; block_size = pBlock->blockSize; assert(block_size >= pBlock->allocatedBytes); assert(s_memStatis.ram_lost >= (block_size - pBlock->allocatedBytes)); /* as the buffer is free, the ram is not "lost" anymore */ s_memStatis.ram_lost -= (block_size - pBlock->allocatedBytes); } #endif #if defined(MEM_STATISTICS_INTERNAL) static void MEM_Reports_memStatis(void) { MEM_DBG_LOG("**************** MEM STATS REPORT **************"); MEM_DBG_LOG("Nb Alloc: %d\r\n", s_memStatis.nb_alloc); MEM_DBG_LOG("Small buffers: %d\r\n", s_memStatis.nb_small_buffer); MEM_DBG_LOG("Medium buffers: %d\r\n", s_memStatis.nb_medium_buffer); MEM_DBG_LOG("Large buffers: %d\r\n", s_memStatis.nb_large_buffer); MEM_DBG_LOG("Peak small: %d\r\n ", s_memStatis.peak_small_buffer); MEM_DBG_LOG("Peak medium: %d\r\n ", s_memStatis.peak_medium_buffer); MEM_DBG_LOG("Peak large: %d\r\n ", s_memStatis.peak_large_buffer); MEM_DBG_LOG("Current RAM allocated: %d bytes\r\n", s_memStatis.ram_allocated); MEM_DBG_LOG("Peak RAM allocated: %d bytes\r\n", s_memStatis.peak_ram_allocated); MEM_DBG_LOG("Current RAM lost: %d bytes\r\n", s_memStatis.ram_lost); MEM_DBG_LOG("Peak RAM lost: %d bytes\r\n", s_memStatis.peak_ram_lost); MEM_DBG_LOG("Peak Upper Address: %x\r\n", s_memStatis.peak_upper_addr); #ifdef MEM_MANAGER_BENCH MEM_DBG_LOG("************************************************\r\n"); MEM_DBG_LOG("********* MEM MANAGER BENCHMARK REPORT *********\r\n"); MEM_DBG_LOG("Last Alloc Time: %d us\r\n", s_memStatis.last_alloc_time); MEM_DBG_LOG("Last Alloc Block Size: %d bytes\r\n", s_memStatis.last_alloc_block_size); MEM_DBG_LOG("Last Alloc Buffer Size: %d bytes\r\n", s_memStatis.last_alloc_buff_size); MEM_DBG_LOG("Average Alloc Time: %d us\r\n", s_memStatis.average_alloc_time); MEM_DBG_LOG("Peak Alloc Time: %d us\r\n", s_memStatis.peak_alloc_time); #endif /* MEM_MANAGER_BENCH */ MEM_DBG_LOG("************************************************"); } #endif /* MEM_STATISTICS_INTERNAL */ /***************************************************************************** ****************************************************************************** * Public functions ****************************************************************************** *****************************************************************************/ /*! * @brief Initialises the Memory Manager. * */ mem_status_t MEM_Init(void) { static bool initialized = false; assert(sizeof(mem_pool_structure_t) == MEM_POOL_SIZE); assert(sizeof(block_list_header_t) == MEM_BLOCK_SIZE); if (!initialized) { s_memmanager.pHeadPool = NULL; s_memmanager.poolNum = 0; #if (defined(MEM_MANAGER_ENABLE_TRACE) && (MEM_MANAGER_ENABLE_TRACE > 0U)) s_memmanager.allocationFailures = 0; s_memmanager.freeFailures = 0; #endif /*MEM_MANAGER_ENABLE_TRACE*/ #if (defined(MEM_MANAGER_PRE_CONFIGURE) && (MEM_MANAGER_PRE_CONFIGURE > 0U)) for (uint8_t i = 0; i < (sizeof(s_PoolList) / sizeof(s_PoolList[0])); i++) { (void)MEM_AddBuffer(s_PoolList[i]); } #endif /*MEM_MANAGER_PRE_CONFIGURE*/ initialized = true; } return kStatus_MemSuccess; } /*! * @brief Add memory buffer to memory manager buffer list. * * @note This API should be called when need add memory buffer to memory manager buffer list. First use * MEM_BLOCK_BUFFER_DEFINE to * define memory buffer, then call MEM_AddBuffer function with MEM_BLOCK_BUFFER Macro. * @code * MEM_BLOCK_BUFFER_DEFINE(app64, 5, 64,0); * MEM_BLOCK_BUFFER_DEFINE(app128, 6, 128,0); * MEM_BLOCK_BUFFER_DEFINE(app256, 7, 256,0); * * MEM_AddBuffer(MEM_BLOCK_BUFFER(app64)); * MEM_AddBuffer(MEM_BLOCK_BUFFER(app128)); * MEM_AddBuffer(MEM_BLOCK_BUFFER(app256)); * @endcode * * @param buffer Pointer the memory pool buffer, use MEM_BLOCK_BUFFER Macro as the input parameter. * * @retval kStatus_MemSuccess Memory manager add Buffer succeed. * @retval kStatus_MemInitError Memory manager add Buffer error occurred. */ mem_status_t MEM_AddBuffer(const uint8_t *buffer) { mem_config_t *memConfig = (mem_config_t *)(void *)buffer; mem_pool_structure_t *pPool = (mem_pool_structure_t *)(void *)memConfig->pbuffer; uint8_t *pHeap = &memConfig->pbuffer[sizeof(mem_pool_structure_t)]; mem_pool_structure_t *pPrevPool, *pTempPool; assert(buffer); assert(memConfig->numberOfBlocks); assert(memConfig->blockSize); MEM_ENTER_CRITICAL(); #if (defined(MEM_MANAGER_PRE_CONFIGURE) && (MEM_MANAGER_PRE_CONFIGURE == 0U)) (void)MEM_Init(); #endif pPool->pHeap = pHeap; pPool->numBlocks = memConfig->numberOfBlocks; pPool->blockSize = memConfig->blockSize; pPool->poolId = *(uint16_t *)(void *)(&buffer[4]); pPool->heapSize = (MEM_POOL_SIZE + (uint32_t)memConfig->numberOfBlocks * (MEM_BLOCK_SIZE + (uint32_t)memConfig->blockSize)); #if (defined(MEM_MANAGER_ENABLE_TRACE) && (MEM_MANAGER_ENABLE_TRACE > 0U)) pPool->allocatedBlocksPeak = 0; pPool->poolTotalFragmentWaste = 0; pPool->poolFragmentWaste = 0; pPool->poolFragmentWastePeak = 0; pPool->poolFragmentMinWaste = 0xffff; #endif /*MEM_MANAGER_ENABLE_TRACE*/ if (s_memmanager.pHeadPool == NULL) { s_memmanager.pHeadPool = pPool; } else { pTempPool = s_memmanager.pHeadPool; pPrevPool = pTempPool; while (NULL != pTempPool) { if (((pPool->blockSize >= pPrevPool->blockSize) && (pPool->blockSize <= pTempPool->blockSize)) || (pPool->blockSize <= pPrevPool->blockSize)) { if (pTempPool == s_memmanager.pHeadPool) { s_memmanager.pHeadPool = pPool; } else { pPrevPool->nextPool = pPool; } pPool->nextPool = pTempPool; break; } pPrevPool = pTempPool; pTempPool = pTempPool->nextPool; } if (pPool->blockSize > pPrevPool->blockSize) { pPrevPool->nextPool = pPool; } } s_memmanager.poolNum++; MEM_EXIT_CRITICAL(); return kStatus_MemSuccess; } /*! * @brief Remove memory buffer from memory manager buffer list. * * @note This API should be called when need remove memory buffer to memory manager buffer list. Use with * MEM_BLOCK_BUFFER Macro as input parameter. * * @param buffer Pointer the memory pool buffer, use MEM_BLOCK_BUFFER Macro as the input parameter. * * @retval kStatus_MemSuccess Memory manager remove buffer succeed. * @retval kStatus_MemUnknownError Memory manager remove buffer error occurred. */ #if (defined(MEM_MANAGER_BUFFER_REMOVE) && (MEM_MANAGER_BUFFER_REMOVE > 0U)) mem_status_t MEM_RemoveBuffer(uint8_t *buffer) { mem_config_t *memConfig = (mem_config_t *)(void *)buffer; mem_pool_structure_t *pPool = (mem_pool_structure_t *)(void *)memConfig->pbuffer; uint8_t *pHeap = &memConfig->pbuffer[sizeof(mem_pool_structure_t)]; mem_pool_structure_t *pPrevPool, *pTempPool; assert(buffer); assert(memConfig->numberOfBlocks > 0U); assert(memConfig->blockSize > 0U); MEM_ENTER_CRITICAL(); pTempPool = s_memmanager.pHeadPool; pPrevPool = pTempPool; while (NULL != pTempPool) { if (0U != pPool->allocatedBlocks) { break; } if (pTempPool->pHeap == pHeap) { if (pPool == s_memmanager.pHeadPool) { s_memmanager.pHeadPool = pPool->nextPool; } else { pPrevPool->nextPool = pPool->nextPool; } s_memmanager.poolNum--; MEM_EXIT_CRITICAL(); return kStatus_MemSuccess; } pPrevPool = pTempPool; pTempPool = pTempPool->nextPool; } MEM_EXIT_CRITICAL(); return kStatus_MemUnknownError; } #endif /* MEM_MANAGER_BUFFER_REMOVE */ /*! * @brief Allocate a block from the memory pools. The function uses the * numBytes argument to look up a pool with adequate block sizes. * * @param numBytes The number of bytes will be allocated. * @param poolId The ID of the pool where to search for a free buffer. * @retval Memory buffer address when allocate success, NULL when allocate fail. */ void *MEM_BufferAllocWithId(uint32_t numBytes, uint8_t poolId) { #if (defined(MEM_MANAGER_ENABLE_TRACE) && (MEM_MANAGER_ENABLE_TRACE > 0U)) uint32_t fragmentWaste = 0; #endif /*MEM_MANAGER_ENABLE_TRACE*/ mem_pool_structure_t *pPool = s_memmanager.pHeadPool; block_list_header_t *pBlock; void *buffer = NULL; MEM_ENTER_CRITICAL(); #ifdef MEM_MANAGER_BENCH uint32_t START_TIME = 0U, STOP_TIME = 0U, ALLOC_TIME = 0U; START_TIME = TM_GetTimestamp(); #endif /* MEM_MANAGER_BENCH */ while (0U != numBytes) { if ((numBytes <= pPool->blockSize) && (pPool->poolId == poolId)) { for (uint32_t i = 0; i < pPool->numBlocks; i++) { pBlock = (block_list_header_t *)(void *)(pPool->pHeap + i * ((uint32_t)pPool->blockSize + (uint32_t)sizeof(block_list_header_t))); if (0U == pBlock->allocated) { pBlock->allocated = 1; pBlock->blockSize = pPool->blockSize; #if (defined(MEM_MANAGER_ENABLE_TRACE) && (MEM_MANAGER_ENABLE_TRACE > 0U)) pBlock->allocatedBytes = (uint16_t)numBytes; pBlock->caller = (uint32_t)((uint32_t *)__mem_get_LR()); #endif /*MEM_MANAGER_ENABLE_TRACE*/ pBlock++; pPool->allocatedBlocks++; buffer = pBlock; (void)memset(buffer, 0x0, pBlock->blockSize); break; } } } if (NULL != buffer) { break; } /* Try next pool*/ pPool = pPool->nextPool; if (NULL == pPool) { break; } } #ifdef MEM_MANAGER_BENCH STOP_TIME = TM_GetTimestamp(); ALLOC_TIME = STOP_TIME - START_TIME; #endif /* MEM_MANAGER_BENCH */ #if (defined(MEM_MANAGER_ENABLE_TRACE) && (MEM_MANAGER_ENABLE_TRACE > 0U)) if (NULL == buffer) { s_memmanager.allocationFailures++; } #endif /*MEM_MANAGER_ENABLE_TRACE*/ #ifdef MEM_STATISTICS_INTERNAL #ifdef MEM_MANAGER_BENCH MEM_BufferAllocates_memStatis(buffer, ALLOC_TIME, numBytes); #else MEM_BufferAllocates_memStatis(buffer, 0, numBytes); #endif if ((s_memStatis.nb_alloc % NB_ALLOC_REPORT_THRESHOLD) == 0U) { MEM_Reports_memStatis(); } #endif /* MEM_STATISTICS_INTERNAL */ #if (defined(MEM_MANAGER_ENABLE_TRACE) && (MEM_MANAGER_ENABLE_TRACE > 0U)) if (pPool->allocatedBlocks > pPool->allocatedBlocksPeak) { pPool->allocatedBlocksPeak = pPool->allocatedBlocks; } fragmentWaste = pPool->blockSize - numBytes; if (fragmentWaste > pPool->poolFragmentWastePeak) { pPool->poolFragmentWastePeak = (uint16_t)fragmentWaste; } pPool->poolFragmentWaste = (uint16_t)fragmentWaste; pPool->poolTotalFragmentWaste += (uint16_t)fragmentWaste; if (fragmentWaste < pPool->poolFragmentMinWaste) { pPool->poolFragmentMinWaste = (uint16_t)fragmentWaste; } #endif /*MEM_MANAGER_ENABLE_TRACE*/ MEM_EXIT_CRITICAL(); return buffer; } /*! * @brief Memory buffer free. * * @param buffer The memory buffer address will be free. * @retval kStatus_MemSuccess Memory free succeed. * @retval kStatus_MemFreeError Memory free error occurred. */ mem_status_t MEM_BufferFree(void *buffer /* IN: Block of memory to free*/ ) { block_list_header_t *pBlock; mem_pool_structure_t *pPool = s_memmanager.pHeadPool; MEM_ENTER_CRITICAL(); do { if (NULL == buffer) { break; } #if defined(MEM_STATISTICS_INTERNAL) MEM_BufferFrees_memStatis(buffer); #endif /* MEM_STATISTICS_INTERNAL */ pBlock = (block_list_header_t *)buffer - 1; assert(pBlock); if (1U == pBlock->allocated) { (void)memset(pBlock, 0x0, (sizeof(block_list_header_t) + (uint32_t)pBlock->blockSize)); MEM_EXIT_CRITICAL(); while (true) { if (((uint32_t)pPool->pHeap <= (uint32_t)pBlock) && ((uint32_t)pBlock < (uint32_t)pPool->pHeap + pPool->numBlocks * ((uint32_t)pPool->blockSize + (uint32_t)sizeof(block_list_header_t)))) { pPool->allocatedBlocks--; return kStatus_MemSuccess; } pPool = pPool->nextPool; if (NULL == pPool) { return kStatus_MemFreeError; } } } #if (defined(MEM_MANAGER_ENABLE_TRACE) && (MEM_MANAGER_ENABLE_TRACE > 0U)) s_memmanager.freeFailures++; #endif /*MEM_MANAGER_ENABLE_TRACE*/ } while (false); MEM_EXIT_CRITICAL(); return kStatus_MemFreeError; } /*! * @brief Returns the size of a given buffer. * * @param buffer The memory buffer address will be free. * @retval The size of a given buffer. */ uint16_t MEM_BufferGetSize(void *buffer) /* IN: Block of memory to get size*/ { block_list_header_t *pBlock; assert(buffer); pBlock = (block_list_header_t *)buffer - 1; assert(pBlock); return pBlock->blockSize; } /*! * @brief Frees all allocated blocks by selected source and in selected pool. * * @param poolId Selected pool Id (4 LSBs of poolId parameter) and selected * source Id (4 MSBs of poolId parameter). * @retval kStatus_MemSuccess Memory free succeed. * @retval kStatus_MemFreeError Memory free error occurred. */ mem_status_t MEM_BufferFreeAllWithId(uint8_t poolId) { mem_pool_structure_t *pPool = s_memmanager.pHeadPool; MEM_ENTER_CRITICAL(); while (pPool != NULL) { if (pPool->poolId == poolId) { (void)memset(pPool->pHeap, 0x0, ((sizeof(block_list_header_t) + (uint32_t)pPool->blockSize) * pPool->numBlocks)); #if (defined(MEM_MANAGER_ENABLE_TRACE) && (MEM_MANAGER_ENABLE_TRACE > 0U)) pPool->allocatedBlocksPeak = 0; pPool->poolTotalFragmentWaste = 0; pPool->poolFragmentWaste = 0; pPool->poolFragmentWastePeak = 0; pPool->poolFragmentMinWaste = 0xffff; #endif /*MEM_MANAGER_ENABLE_TRACE*/ pPool->allocatedBlocks = 0; } pPool = pPool->nextPool; } MEM_EXIT_CRITICAL(); return kStatus_MemSuccess; } /*! * @brief Memory buffer realloc. * * @param buffer The memory buffer address will be reallocated. * @param new_size The number of bytes will be reallocated * @retval kStatus_MemSuccess Memory free succeed. * @retval kStatus_MemFreeError Memory free error occurred. */ void *MEM_BufferRealloc(void *buffer, uint32_t new_size) { void *realloc_buffer = NULL; uint16_t block_size = 0U; if (new_size == 0U) { /* new requested size is 0, free old buffer */ (void)MEM_BufferFree(buffer); realloc_buffer = NULL; } else if (buffer == NULL) { /* input buffer is NULL simply allocate a new buffer and return it */ realloc_buffer = MEM_BufferAllocWithId(new_size, 0U); } else { block_size = MEM_BufferGetSize(buffer); if ((uint16_t)new_size <= block_size) { /* current buffer is large enough for the new requested size we can still use it */ realloc_buffer = buffer; } else { /* not enough space in the current block, creating a new one */ realloc_buffer = MEM_BufferAllocWithId(new_size, 0U); if (realloc_buffer != NULL) { /* copy input buffer data to new buffer */ (void)memcpy(realloc_buffer, buffer, (uint32_t)block_size); /* free old buffer */ (void)MEM_BufferFree(buffer); } } } return realloc_buffer; } /*! * @brief Get the address after the last allocated block if MemManagerLight is used. * * @retval 0 Return 0 in case of the legacy MemManager. */ uint32_t MEM_GetHeapUpperLimit(void) { return 0U; } /*! * @brief Get the free space in the heap. * * @retval 0 Return 0 in case of the legacy MemManager. */ uint32_t MEM_GetFreeHeapSize(void) { return 0U; } /*! * @brief Trace memory manager all information to use debug. * */ #if (defined(MEM_MANAGER_ENABLE_TRACE) && (MEM_MANAGER_ENABLE_TRACE > 0U)) void MEM_Trace(void) { mem_pool_structure_t *pPool = s_memmanager.pHeadPool; block_list_header_t *pBlock; (void)PRINTF("MEM_Trace debug information, Pools Number:%d allocationFailures: %d freeFailures:%d \r\n", s_memmanager.poolNum, s_memmanager.allocationFailures, s_memmanager.allocationFailures, s_memmanager.freeFailures); while (NULL != pPool) { (void)PRINTF("POOL: ID %d blockSize:%d status:\r\n", pPool->poolId, pPool->blockSize); (void)PRINTF( "numBlocks allocatedBlocks allocatedBlocksPeak poolFragmentWaste poolFragmentWastePeak " "poolFragmentMinWaste poolTotalFragmentWaste\r\n"); (void)PRINTF( " %d %d %d %d %d %d " " %d \r\n", pPool->numBlocks, pPool->allocatedBlocks, pPool->allocatedBlocksPeak, pPool->poolFragmentWaste, pPool->poolFragmentWastePeak, pPool->poolFragmentMinWaste, pPool->poolTotalFragmentWaste); (void)PRINTF("Currently pool meory block allocate status: \r\n"); for (uint32_t i = 0; i < pPool->numBlocks; i++) { pBlock = (block_list_header_t *)(void *)(pPool->pHeap + i * ((uint32_t)pPool->blockSize + sizeof(block_list_header_t))); (void)PRINTF("Block %d caller : 0x%x Allocated %d bytes: %d \r\n", i, pBlock->caller, pBlock->allocated, pBlock->allocatedBytes); } /* Try next pool*/ pPool = pPool->nextPool; } } #endif /*MEM_MANAGER_ENABLE_TRACE*/ #endif /*gMemManagerLight*/