mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Add xPortGetFreeHeapSizeCaps and xPortGetMinimumEverFreeHeapSizeCaps plus everything it entails. Allows querying the available memory for various capabilities. Also: xPortGetFreeHeapSize and xPortGetMinimumEverFreeHeapSize now return the expected value. Bonus: the linked list used in the allocator is now 4 bytes smaller, which should save some memory.
This commit is contained in:
parent
3f3cf397f7
commit
293ad4cd36
@ -43,6 +43,7 @@ typedef struct {
|
|||||||
/*
|
/*
|
||||||
Tag descriptors. These describe the capabilities of a bit of memory that's tagged with the index into this table.
|
Tag descriptors. These describe the capabilities of a bit of memory that's tagged with the index into this table.
|
||||||
Each tag contains NO_PRIOS entries; later entries are only taken if earlier ones can't fulfill the memory request.
|
Each tag contains NO_PRIOS entries; later entries are only taken if earlier ones can't fulfill the memory request.
|
||||||
|
Make sure there are never more than HEAPREGIONS_MAX_TAGCOUNT (in heap_regions.h) tags (ex the last empty marker)
|
||||||
*/
|
*/
|
||||||
static const tag_desc_t tag_desc[]={
|
static const tag_desc_t tag_desc[]={
|
||||||
{ "DRAM", { MALLOC_CAP_DMA|MALLOC_CAP_8BIT, MALLOC_CAP_32BIT, 0 }}, //Tag 0: Plain ole D-port RAM
|
{ "DRAM", { MALLOC_CAP_DMA|MALLOC_CAP_8BIT, MALLOC_CAP_32BIT, 0 }}, //Tag 0: Plain ole D-port RAM
|
||||||
@ -268,3 +269,52 @@ void *pvPortMallocCaps( size_t xWantedSize, uint32_t caps )
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t xPortGetFreeHeapSizeCaps( uint32_t caps )
|
||||||
|
{
|
||||||
|
int prio;
|
||||||
|
int tag;
|
||||||
|
size_t ret=0;
|
||||||
|
for (prio=0; prio<NO_PRIOS; prio++) {
|
||||||
|
//Iterate over tag descriptors for this priority
|
||||||
|
for (tag=0; tag_desc[tag].prio[prio]!=MALLOC_CAP_INVALID; tag++) {
|
||||||
|
if ((tag_desc[tag].prio[prio]&caps)!=0) {
|
||||||
|
ret+=xPortGetFreeHeapSizeTagged(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t xPortGetMinimumEverFreeHeapSizeCaps( uint32_t caps )
|
||||||
|
{
|
||||||
|
int prio;
|
||||||
|
int tag;
|
||||||
|
size_t ret=0;
|
||||||
|
for (prio=0; prio<NO_PRIOS; prio++) {
|
||||||
|
//Iterate over tag descriptors for this priority
|
||||||
|
for (tag=0; tag_desc[tag].prio[prio]!=MALLOC_CAP_INVALID; tag++) {
|
||||||
|
if ((tag_desc[tag].prio[prio]&caps)!=0) {
|
||||||
|
ret+=xPortGetMinimumEverFreeHeapSizeTagged(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t xPortGetFreeHeapSize( void )
|
||||||
|
{
|
||||||
|
return xPortGetFreeHeapSizeCaps( MALLOC_CAP_8BIT );
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t xPortGetMinimumEverFreeHeapSize( void )
|
||||||
|
{
|
||||||
|
return xPortGetMinimumEverFreeHeapSizeCaps( MALLOC_CAP_8BIT );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,5 +30,7 @@
|
|||||||
|
|
||||||
void heap_alloc_caps_init();
|
void heap_alloc_caps_init();
|
||||||
void *pvPortMallocCaps(size_t xWantedSize, uint32_t caps);
|
void *pvPortMallocCaps(size_t xWantedSize, uint32_t caps);
|
||||||
|
size_t xPortGetFreeHeapSizeCaps( uint32_t caps );
|
||||||
|
size_t xPortGetMinimumEverFreeHeapSizeCaps( uint32_t caps );
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -148,11 +148,13 @@ task.h is included from an application file. */
|
|||||||
|
|
||||||
/* Define the linked list structure. This is used to link free blocks in order
|
/* Define the linked list structure. This is used to link free blocks in order
|
||||||
of their memory address. */
|
of their memory address. */
|
||||||
|
/* This is optimized and assumes a region is never larger than 16MiB. */
|
||||||
typedef struct A_BLOCK_LINK
|
typedef struct A_BLOCK_LINK
|
||||||
{
|
{
|
||||||
struct A_BLOCK_LINK *pxNextFreeBlock; /*<< The next free block in the list. */
|
struct A_BLOCK_LINK *pxNextFreeBlock; /*<< The next free block in the list. */
|
||||||
size_t xBlockSize; /*<< The size of the free block. */
|
int xBlockSize: 24; /*<< The size of the free block. */
|
||||||
BaseType_t xTag; /*<< Tag of this region */
|
int xTag: 7; /*<< Tag of this region */
|
||||||
|
int xAllocated: 1; /*<< 1 if allocated */
|
||||||
} BlockLink_t;
|
} BlockLink_t;
|
||||||
|
|
||||||
//Mux to protect the memory status data
|
//Mux to protect the memory status data
|
||||||
@ -179,14 +181,9 @@ static BlockLink_t xStart, *pxEnd = NULL;
|
|||||||
|
|
||||||
/* Keeps track of the number of free bytes remaining, but says nothing about
|
/* Keeps track of the number of free bytes remaining, but says nothing about
|
||||||
fragmentation. */
|
fragmentation. */
|
||||||
static size_t xFreeBytesRemaining = 0;
|
static size_t xFreeBytesRemaining[HEAPREGIONS_MAX_TAGCOUNT] = {0};
|
||||||
static size_t xMinimumEverFreeBytesRemaining = 0;
|
static size_t xMinimumEverFreeBytesRemaining[HEAPREGIONS_MAX_TAGCOUNT] = {0};
|
||||||
|
|
||||||
/* Gets set to the top bit of an size_t type. When this bit in the xBlockSize
|
|
||||||
member of an BlockLink_t structure is set then the block belongs to the
|
|
||||||
application. When the bit is free the block is still part of the free heap
|
|
||||||
space. */
|
|
||||||
static size_t xBlockAllocatedBit = 0;
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
@ -201,126 +198,115 @@ void *pvReturn = NULL;
|
|||||||
|
|
||||||
taskENTER_CRITICAL(&xMallocMutex);
|
taskENTER_CRITICAL(&xMallocMutex);
|
||||||
{
|
{
|
||||||
/* Check the requested block size is not so large that the top bit is
|
/* The wanted size is increased so it can contain a BlockLink_t
|
||||||
set. The top bit of the block size member of the BlockLink_t structure
|
structure in addition to the requested amount of bytes. */
|
||||||
is used to determine who owns the block - the application or the
|
if( xWantedSize > 0 )
|
||||||
kernel, so it must be free. */
|
|
||||||
if( ( xWantedSize & xBlockAllocatedBit ) == 0 )
|
|
||||||
{
|
{
|
||||||
/* The wanted size is increased so it can contain a BlockLink_t
|
xWantedSize += uxHeapStructSize;
|
||||||
structure in addition to the requested amount of bytes. */
|
|
||||||
if( xWantedSize > 0 )
|
|
||||||
{
|
|
||||||
xWantedSize += uxHeapStructSize;
|
|
||||||
|
|
||||||
/* Ensure that blocks are always aligned to the required number
|
/* Ensure that blocks are always aligned to the required number
|
||||||
of bytes. */
|
of bytes. */
|
||||||
if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 )
|
if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 )
|
||||||
{
|
{
|
||||||
/* Byte alignment required. */
|
/* Byte alignment required. */
|
||||||
xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
|
xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mtCOVERAGE_TEST_MARKER();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mtCOVERAGE_TEST_MARKER();
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining[ tag ] ) )
|
||||||
|
{
|
||||||
|
/* Traverse the list from the start (lowest address) block until
|
||||||
|
one of adequate size is found. */
|
||||||
|
pxPreviousBlock = &xStart;
|
||||||
|
pxBlock = xStart.pxNextFreeBlock;
|
||||||
|
while( ( ( pxBlock->xTag != tag ) || ( pxBlock->xBlockSize < xWantedSize ) ) && ( pxBlock->pxNextFreeBlock != NULL ) )
|
||||||
|
{
|
||||||
|
// ets_printf("Block %x -> %x\n", (uint32_t)pxBlock, (uint32_t)pxBlock->pxNextFreeBlock);
|
||||||
|
|
||||||
|
#if (configENABLE_MEMORY_DEBUG == 1)
|
||||||
|
{
|
||||||
|
mem_check_block(pxBlock);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pxPreviousBlock = pxBlock;
|
||||||
|
pxBlock = pxBlock->pxNextFreeBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) )
|
/* If the end marker was not reached then a block of adequate size
|
||||||
|
was found. */
|
||||||
|
if( pxBlock != pxEnd )
|
||||||
{
|
{
|
||||||
/* Traverse the list from the start (lowest address) block until
|
/* Return the memory space pointed to - jumping over the
|
||||||
one of adequate size is found. */
|
BlockLink_t structure at its start. */
|
||||||
pxPreviousBlock = &xStart;
|
pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + uxHeapStructSize - BLOCK_TAIL_LEN - BLOCK_HEAD_LEN);
|
||||||
pxBlock = xStart.pxNextFreeBlock;
|
|
||||||
while( ( ( pxBlock->xTag != tag ) || ( pxBlock->xBlockSize < xWantedSize ) ) && ( pxBlock->pxNextFreeBlock != NULL ) )
|
/* This block is being returned for use so must be taken out
|
||||||
|
of the list of free blocks. */
|
||||||
|
pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
|
||||||
|
|
||||||
|
/* If the block is larger than required it can be split into
|
||||||
|
two. */
|
||||||
|
|
||||||
|
if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE )
|
||||||
{
|
{
|
||||||
// ets_printf("Block %x -> %x\n", (uint32_t)pxBlock, (uint32_t)pxBlock->pxNextFreeBlock);
|
/* This block is to be split into two. Create a new
|
||||||
|
block following the number of bytes requested. The void
|
||||||
|
cast is used to prevent byte alignment warnings from the
|
||||||
|
compiler. */
|
||||||
|
pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize);
|
||||||
|
|
||||||
#if (configENABLE_MEMORY_DEBUG == 1)
|
/* Calculate the sizes of two blocks split from the
|
||||||
{
|
single block. */
|
||||||
mem_check_block(pxBlock);
|
pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
|
||||||
}
|
pxNewBlockLink->xTag = tag;
|
||||||
#endif
|
pxBlock->xBlockSize = xWantedSize;
|
||||||
|
|
||||||
pxPreviousBlock = pxBlock;
|
#if (configENABLE_MEMORY_DEBUG == 1)
|
||||||
pxBlock = pxBlock->pxNextFreeBlock;
|
{
|
||||||
}
|
mem_init_dog(pxNewBlockLink);
|
||||||
|
}
|
||||||
/* If the end marker was not reached then a block of adequate size
|
#endif
|
||||||
was found. */
|
|
||||||
if( pxBlock != pxEnd )
|
|
||||||
{
|
|
||||||
/* Return the memory space pointed to - jumping over the
|
|
||||||
BlockLink_t structure at its start. */
|
|
||||||
pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + uxHeapStructSize - BLOCK_TAIL_LEN - BLOCK_HEAD_LEN);
|
|
||||||
|
|
||||||
/* This block is being returned for use so must be taken out
|
|
||||||
of the list of free blocks. */
|
|
||||||
pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
|
|
||||||
|
|
||||||
/* If the block is larger than required it can be split into
|
|
||||||
two. */
|
|
||||||
|
|
||||||
if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE )
|
|
||||||
{
|
|
||||||
/* This block is to be split into two. Create a new
|
|
||||||
block following the number of bytes requested. The void
|
|
||||||
cast is used to prevent byte alignment warnings from the
|
|
||||||
compiler. */
|
|
||||||
pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize);
|
|
||||||
|
|
||||||
/* Calculate the sizes of two blocks split from the
|
|
||||||
single block. */
|
|
||||||
pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
|
|
||||||
pxNewBlockLink->xTag = tag;
|
|
||||||
pxBlock->xBlockSize = xWantedSize;
|
|
||||||
|
|
||||||
#if (configENABLE_MEMORY_DEBUG == 1)
|
|
||||||
{
|
|
||||||
mem_init_dog(pxNewBlockLink);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Insert the new block into the list of free blocks. */
|
/* Insert the new block into the list of free blocks. */
|
||||||
prvInsertBlockIntoFreeList( ( pxNewBlockLink ) );
|
prvInsertBlockIntoFreeList( ( pxNewBlockLink ) );
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mtCOVERAGE_TEST_MARKER();
|
|
||||||
}
|
|
||||||
|
|
||||||
xFreeBytesRemaining -= pxBlock->xBlockSize;
|
|
||||||
|
|
||||||
if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining )
|
|
||||||
{
|
|
||||||
xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mtCOVERAGE_TEST_MARKER();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The block is being returned - it is allocated and owned
|
|
||||||
by the application and has no "next" block. */
|
|
||||||
pxBlock->xBlockSize |= xBlockAllocatedBit;
|
|
||||||
pxBlock->pxNextFreeBlock = NULL;
|
|
||||||
|
|
||||||
#if (configENABLE_MEMORY_DEBUG == 1)
|
|
||||||
{
|
|
||||||
mem_init_dog(pxBlock);
|
|
||||||
mem_malloc_block(pxBlock);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mtCOVERAGE_TEST_MARKER();
|
mtCOVERAGE_TEST_MARKER();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xFreeBytesRemaining[ tag ] -= pxBlock->xBlockSize;
|
||||||
|
|
||||||
|
if( xFreeBytesRemaining[ tag ] < xMinimumEverFreeBytesRemaining[ tag ] )
|
||||||
|
{
|
||||||
|
xMinimumEverFreeBytesRemaining[ tag ] = xFreeBytesRemaining[ tag ];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The block is being returned - it is allocated and owned
|
||||||
|
by the application and has no "next" block. */
|
||||||
|
pxBlock->xAllocated = 1;
|
||||||
|
pxBlock->pxNextFreeBlock = NULL;
|
||||||
|
|
||||||
|
#if (configENABLE_MEMORY_DEBUG == 1)
|
||||||
|
{
|
||||||
|
mem_init_dog(pxBlock);
|
||||||
|
mem_malloc_block(pxBlock);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -378,21 +364,21 @@ BlockLink_t *pxLink;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Check the block is actually allocated. */
|
/* Check the block is actually allocated. */
|
||||||
configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 );
|
configASSERT( ( pxLink->xAllocated ) != 0 );
|
||||||
configASSERT( pxLink->pxNextFreeBlock == NULL );
|
configASSERT( pxLink->pxNextFreeBlock == NULL );
|
||||||
|
|
||||||
if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 )
|
if( pxLink->xAllocated != 0 )
|
||||||
{
|
{
|
||||||
if( pxLink->pxNextFreeBlock == NULL )
|
if( pxLink->pxNextFreeBlock == NULL )
|
||||||
{
|
{
|
||||||
/* The block is being returned to the heap - it is no longer
|
/* The block is being returned to the heap - it is no longer
|
||||||
allocated. */
|
allocated. */
|
||||||
pxLink->xBlockSize &= ~xBlockAllocatedBit;
|
pxLink->xAllocated = 0;
|
||||||
|
|
||||||
taskENTER_CRITICAL(&xMallocMutex);
|
taskENTER_CRITICAL(&xMallocMutex);
|
||||||
{
|
{
|
||||||
/* Add this block to the list of free blocks. */
|
/* Add this block to the list of free blocks. */
|
||||||
xFreeBytesRemaining += pxLink->xBlockSize;
|
xFreeBytesRemaining[ pxLink->xTag ] += pxLink->xBlockSize;
|
||||||
traceFREE( pv, pxLink->xBlockSize );
|
traceFREE( pv, pxLink->xBlockSize );
|
||||||
prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
|
prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
|
||||||
}
|
}
|
||||||
@ -411,15 +397,15 @@ BlockLink_t *pxLink;
|
|||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
size_t xPortGetFreeHeapSize( void )
|
size_t xPortGetFreeHeapSizeTagged( BaseType_t tag )
|
||||||
{
|
{
|
||||||
return xFreeBytesRemaining;
|
return xFreeBytesRemaining[ tag ];
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
size_t xPortGetMinimumEverFreeHeapSize( void )
|
size_t xPortGetMinimumEverFreeHeapSizeTagged( BaseType_t tag )
|
||||||
{
|
{
|
||||||
return xMinimumEverFreeBytesRemaining;
|
return xMinimumEverFreeBytesRemaining[ tag ];
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
@ -509,6 +495,7 @@ const HeapRegionTagged_t *pxHeapRegion;
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
configASSERT(pxHeapRegion->xTag < HEAPREGIONS_MAX_TAGCOUNT);
|
||||||
xTotalRegionSize = pxHeapRegion->xSizeInBytes;
|
xTotalRegionSize = pxHeapRegion->xSizeInBytes;
|
||||||
|
|
||||||
/* Ensure the heap region starts on a correctly aligned boundary. */
|
/* Ensure the heap region starts on a correctly aligned boundary. */
|
||||||
@ -572,6 +559,8 @@ const HeapRegionTagged_t *pxHeapRegion;
|
|||||||
}
|
}
|
||||||
|
|
||||||
xTotalHeapSize += pxFirstFreeBlockInRegion->xBlockSize;
|
xTotalHeapSize += pxFirstFreeBlockInRegion->xBlockSize;
|
||||||
|
xMinimumEverFreeBytesRemaining[ pxHeapRegion->xTag ] += pxFirstFreeBlockInRegion->xBlockSize;
|
||||||
|
xFreeBytesRemaining[ pxHeapRegion->xTag ] += pxFirstFreeBlockInRegion->xBlockSize;
|
||||||
|
|
||||||
/* Move onto the next HeapRegionTagged_t structure. */
|
/* Move onto the next HeapRegionTagged_t structure. */
|
||||||
xDefinedRegions++;
|
xDefinedRegions++;
|
||||||
@ -586,14 +575,9 @@ const HeapRegionTagged_t *pxHeapRegion;
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
xMinimumEverFreeBytesRemaining = xTotalHeapSize;
|
|
||||||
xFreeBytesRemaining = xTotalHeapSize;
|
|
||||||
|
|
||||||
/* Check something was actually defined before it is accessed. */
|
/* Check something was actually defined before it is accessed. */
|
||||||
configASSERT( xTotalHeapSize );
|
configASSERT( xTotalHeapSize );
|
||||||
|
|
||||||
/* Work out the position of the top bit in a size_t variable. */
|
|
||||||
xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 );
|
|
||||||
|
|
||||||
#if (configENABLE_MEMORY_DEBUG == 1)
|
#if (configENABLE_MEMORY_DEBUG == 1)
|
||||||
{
|
{
|
||||||
|
@ -12,19 +12,17 @@ static size_t g_heap_struct_size;
|
|||||||
static mem_dbg_ctl_t g_mem_dbg;
|
static mem_dbg_ctl_t g_mem_dbg;
|
||||||
char g_mem_print = 0;
|
char g_mem_print = 0;
|
||||||
static portMUX_TYPE *g_malloc_mutex = NULL;
|
static portMUX_TYPE *g_malloc_mutex = NULL;
|
||||||
static unsigned int g_alloc_bit;
|
|
||||||
#define MEM_DEBUG(...)
|
#define MEM_DEBUG(...)
|
||||||
|
|
||||||
void mem_debug_init(size_t size, void *start, void *end, portMUX_TYPE *mutex, unsigned int alloc_bit)
|
void mem_debug_init(size_t size, void *start, void *end, portMUX_TYPE *mutex)
|
||||||
{
|
{
|
||||||
MEM_DEBUG("size=%d start=%p end=%p mutex=%p alloc_bit=0x%x\n", size, start, end, mutex, alloc_bit);
|
MEM_DEBUG("size=%d start=%p end=%p mutex=%p%x\n", size, start, end, mutex);
|
||||||
memset(&g_mem_dbg, 0, sizeof(g_mem_dbg));
|
memset(&g_mem_dbg, 0, sizeof(g_mem_dbg));
|
||||||
memset(&g_malloc_list, 0, sizeof(g_malloc_list));
|
memset(&g_malloc_list, 0, sizeof(g_malloc_list));
|
||||||
g_malloc_mutex = mutex;
|
g_malloc_mutex = mutex;
|
||||||
g_heap_struct_size = size;
|
g_heap_struct_size = size;
|
||||||
g_free_list = start;
|
g_free_list = start;
|
||||||
g_end = end;
|
g_end = end;
|
||||||
g_alloc_bit = alloc_bit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mem_debug_push(char type, void *addr)
|
void mem_debug_push(char type, void *addr)
|
||||||
@ -35,9 +33,9 @@ void mem_debug_push(char type, void *addr)
|
|||||||
MEM_DEBUG("push type=%d addr=%p\n", type, addr);
|
MEM_DEBUG("push type=%d addr=%p\n", type, addr);
|
||||||
if (g_mem_print){
|
if (g_mem_print){
|
||||||
if (type == DEBUG_TYPE_MALLOC){
|
if (type == DEBUG_TYPE_MALLOC){
|
||||||
ets_printf("task=%s t=%s s=%u a=%p\n", debug_b->head.task?debug_b->head.task:"", type==DEBUG_TYPE_MALLOC?"m":"f", b->size&(~g_alloc_bit), addr);
|
ets_printf("task=%s t=%s s=%u a=%p\n", debug_b->head.task?debug_b->head.task:"", type==DEBUG_TYPE_MALLOC?"m":"f", b->size, addr);
|
||||||
} else {
|
} else {
|
||||||
ets_printf("task=%s t=%s s=%u a=%p\n", debug_b->head.task?debug_b->head.task:"", type==DEBUG_TYPE_MALLOC?"m":"f", b->size&(~g_alloc_bit), addr);
|
ets_printf("task=%s t=%s s=%u a=%p\n", debug_b->head.task?debug_b->head.task:"", type==DEBUG_TYPE_MALLOC?"m":"f", b->size, addr);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mem_dbg_info_t *info = &g_mem_dbg.info[g_mem_dbg.cnt%DEBUG_MAX_INFO_NUM];
|
mem_dbg_info_t *info = &g_mem_dbg.info[g_mem_dbg.cnt%DEBUG_MAX_INFO_NUM];
|
||||||
@ -58,7 +56,7 @@ void mem_debug_malloc_show(void)
|
|||||||
while (b){
|
while (b){
|
||||||
d = DEBUG_BLOCK(b);
|
d = DEBUG_BLOCK(b);
|
||||||
d->head.task[3] = '\0';
|
d->head.task[3] = '\0';
|
||||||
ets_printf("t=%s s=%u a=%p\n", d->head.task?d->head.task:"", b->size&(~g_alloc_bit), b);
|
ets_printf("t=%s s=%u a=%p\n", d->head.task?d->head.task:"", b->size, b);
|
||||||
b = b->next;
|
b = b->next;
|
||||||
}
|
}
|
||||||
taskEXIT_CRITICAL(g_malloc_mutex);
|
taskEXIT_CRITICAL(g_malloc_mutex);
|
||||||
@ -140,7 +138,7 @@ void mem_malloc_show(void)
|
|||||||
|
|
||||||
while (b){
|
while (b){
|
||||||
debug_b = DEBUG_BLOCK(b);
|
debug_b = DEBUG_BLOCK(b);
|
||||||
ets_printf("%s %p %p %u\n", debug_b->head.task, debug_b, b, b->size&(~g_alloc_bit));
|
ets_printf("%s %p %p %u\n", debug_b->head.task, debug_b, b, b->size);
|
||||||
b = b->next;
|
b = b->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -149,7 +147,7 @@ void mem_malloc_block(void *data)
|
|||||||
{
|
{
|
||||||
os_block_t *b = (os_block_t*)data;
|
os_block_t *b = (os_block_t*)data;
|
||||||
|
|
||||||
MEM_DEBUG("mem malloc block data=%p, size=%u\n", data, b->size&(~g_alloc_bit));
|
MEM_DEBUG("mem malloc block data=%p, size=%u\n", data, b->size);
|
||||||
mem_debug_push(DEBUG_TYPE_MALLOC, data);
|
mem_debug_push(DEBUG_TYPE_MALLOC, data);
|
||||||
|
|
||||||
if (b){
|
if (b){
|
||||||
@ -165,7 +163,7 @@ void mem_free_block(void *data)
|
|||||||
os_block_t *pre = &g_malloc_list;
|
os_block_t *pre = &g_malloc_list;
|
||||||
debug_block_t *debug_b;
|
debug_block_t *debug_b;
|
||||||
|
|
||||||
MEM_DEBUG("mem free block data=%p, size=%d\n", data, del->size&(~g_alloc_bit));
|
MEM_DEBUG("mem free block data=%p, size=%d\n", data, del->size);
|
||||||
mem_debug_push(DEBUG_TYPE_FREE, data);
|
mem_debug_push(DEBUG_TYPE_FREE, data);
|
||||||
|
|
||||||
if (!del) {
|
if (!del) {
|
||||||
@ -183,7 +181,7 @@ void mem_free_block(void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
debug_b = DEBUG_BLOCK(del);
|
debug_b = DEBUG_BLOCK(del);
|
||||||
ets_printf("%s %p %p %u already free\n", debug_b->head.task, debug_b, del, del->size&(~g_alloc_bit));
|
ets_printf("%s %p %p %u already free\n", debug_b->head.task, debug_b, del, del->size);
|
||||||
mem_malloc_show();
|
mem_malloc_show();
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,9 @@
|
|||||||
|
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
|
|
||||||
|
/* The maximum amount of tags in use */
|
||||||
|
#define HEAPREGIONS_MAX_TAGCOUNT 16
|
||||||
|
|
||||||
|
|
||||||
typedef struct HeapRegionTagged
|
typedef struct HeapRegionTagged
|
||||||
{
|
{
|
||||||
@ -28,7 +31,8 @@ typedef struct HeapRegionTagged
|
|||||||
|
|
||||||
void vPortDefineHeapRegionsTagged( const HeapRegionTagged_t * const pxHeapRegions );
|
void vPortDefineHeapRegionsTagged( const HeapRegionTagged_t * const pxHeapRegions );
|
||||||
void *pvPortMallocTagged( size_t xWantedSize, BaseType_t tag );
|
void *pvPortMallocTagged( size_t xWantedSize, BaseType_t tag );
|
||||||
|
size_t xPortGetMinimumEverFreeHeapSizeTagged( BaseType_t tag );
|
||||||
|
size_t xPortGetFreeHeapSizeTagged( BaseType_t tag );
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -60,7 +60,7 @@ typedef struct _mem_dbg_ctl{
|
|||||||
|
|
||||||
extern void mem_check_block(void * data);
|
extern void mem_check_block(void * data);
|
||||||
extern void mem_init_dog(void *data);
|
extern void mem_init_dog(void *data);
|
||||||
extern void mem_debug_init(size_t size, void *start, void *end, portMUX_TYPE *mutex, unsigned int alloc_bit);
|
extern void mem_debug_init(size_t size, void *start, void *end, portMUX_TYPE *mutex);
|
||||||
extern void mem_malloc_block(void *data);
|
extern void mem_malloc_block(void *data);
|
||||||
extern void mem_free_block(void *data);
|
extern void mem_free_block(void *data);
|
||||||
extern void mem_check_all(void* pv);
|
extern void mem_check_all(void* pv);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user