mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-04-20 05:21:59 -04:00
Add vPortGetHeapStats() function to query heap statistics.
This commit is contained in:
parent
7235743749
commit
246bb6e806
|
@ -118,13 +118,26 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Used by heap_5.c. */
|
/* Used by heap_5.c to define the start address and size of each memory region
|
||||||
|
that together comprise the total FreeRTOS heap space. */
|
||||||
typedef struct HeapRegion
|
typedef struct HeapRegion
|
||||||
{
|
{
|
||||||
uint8_t *pucStartAddress;
|
uint8_t *pucStartAddress;
|
||||||
size_t xSizeInBytes;
|
size_t xSizeInBytes;
|
||||||
} HeapRegion_t;
|
} HeapRegion_t;
|
||||||
|
|
||||||
|
/* Used to pass information about the heap out of vPortGetHeapStats(). */
|
||||||
|
typedef struct xHeapStats
|
||||||
|
{
|
||||||
|
size_t xAvailableHeapSpaceInBytes; /* The total heap size currently available - this is the sum of all the free blocks, not the largest block that can be allocated. */
|
||||||
|
size_t xSizeOfLargestFreeBlockInBytes; /* The maximum size, in bytes, of all the free blocks within the heap at the time vPortGetHeapStats() is called. */
|
||||||
|
size_t xSizeOfSmallestFreeBlockInBytes; /* The minimum size, in bytes, of all the free blocks within the heap at the time vPortGetHeapStats() is called. */
|
||||||
|
size_t xNumberOfFreeBlocks; /* The number of free memory blocks within the heap at the time vPortGetHeapStats() is called. */
|
||||||
|
size_t xMinimumEverFreeBytesRemaining; /* The minimum amount of total free memory (sum of all free blocks) there has been in the heap since the system booted. */
|
||||||
|
size_t xNumberOfSuccessfulAllocations; /* The number of calls to pvPortMalloc() that have returned a valid memory block. */
|
||||||
|
size_t xNumberOfSuccessfulFrees; /* The number of calls to vPortFree() that has successfully freed a block of memory. */
|
||||||
|
} HeapStats_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Used to define multiple heap regions for use by heap_5.c. This function
|
* Used to define multiple heap regions for use by heap_5.c. This function
|
||||||
* must be called before any calls to pvPortMalloc() - not creating a task,
|
* must be called before any calls to pvPortMalloc() - not creating a task,
|
||||||
|
@ -138,6 +151,11 @@ typedef struct HeapRegion
|
||||||
*/
|
*/
|
||||||
void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ) PRIVILEGED_FUNCTION;
|
void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns a HeapStats_t structure filled with information about the current
|
||||||
|
* heap state.
|
||||||
|
*/
|
||||||
|
void vPortGetHeapStats( HeapStats_t *pxHeapStats );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Map to the memory management routines required for the port.
|
* Map to the memory management routines required for the port.
|
||||||
|
|
|
@ -97,10 +97,12 @@ static const size_t xHeapStructSize = ( sizeof( BlockLink_t ) + ( ( size_t ) ( p
|
||||||
/* Create a couple of list links to mark the start and end of the list. */
|
/* Create a couple of list links to mark the start and end of the list. */
|
||||||
static BlockLink_t xStart, *pxEnd = NULL;
|
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 calls to allocate and free memory as well as the
|
||||||
fragmentation. */
|
number of free bytes remaining, but says nothing about fragmentation. */
|
||||||
static size_t xFreeBytesRemaining = 0U;
|
static size_t xFreeBytesRemaining = 0U;
|
||||||
static size_t xMinimumEverFreeBytesRemaining = 0U;
|
static size_t xMinimumEverFreeBytesRemaining = 0U;
|
||||||
|
static size_t xNumberOfSuccessfulAllocations = 0;
|
||||||
|
static size_t xNumberOfSuccessfulFrees = 0;
|
||||||
|
|
||||||
/* Gets set to the top bit of an size_t type. When this bit in the xBlockSize
|
/* 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
|
member of an BlockLink_t structure is set then the block belongs to the
|
||||||
|
@ -221,6 +223,7 @@ void *pvReturn = NULL;
|
||||||
by the application and has no "next" block. */
|
by the application and has no "next" block. */
|
||||||
pxBlock->xBlockSize |= xBlockAllocatedBit;
|
pxBlock->xBlockSize |= xBlockAllocatedBit;
|
||||||
pxBlock->pxNextFreeBlock = NULL;
|
pxBlock->pxNextFreeBlock = NULL;
|
||||||
|
xNumberOfSuccessfulAllocations++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -292,6 +295,7 @@ BlockLink_t *pxLink;
|
||||||
xFreeBytesRemaining += pxLink->xBlockSize;
|
xFreeBytesRemaining += pxLink->xBlockSize;
|
||||||
traceFREE( pv, pxLink->xBlockSize );
|
traceFREE( pv, pxLink->xBlockSize );
|
||||||
prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
|
prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
|
||||||
|
xNumberOfSuccessfulFrees++;
|
||||||
}
|
}
|
||||||
( void ) xTaskResumeAll();
|
( void ) xTaskResumeAll();
|
||||||
}
|
}
|
||||||
|
@ -326,6 +330,58 @@ void vPortInitialiseBlocks( void )
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortGetHeapStats( HeapStats_t *pxHeapStats )
|
||||||
|
{
|
||||||
|
BlockLink_t *pxBlock;
|
||||||
|
size_t xBlocks = 0, xMaxSize = 0, xMinSize = 0;
|
||||||
|
|
||||||
|
vTaskSuspendAll();
|
||||||
|
{
|
||||||
|
pxBlock = xStart.pxNextFreeBlock;
|
||||||
|
|
||||||
|
/* pxBlock will be NULL if the heap has not been initialised. The heap
|
||||||
|
is initialised automatically when the first allocation is made. */
|
||||||
|
if( pxBlock != NULL )
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
/* Increment the number of blocks and record the largest block seen
|
||||||
|
so far. */
|
||||||
|
xBlocks++;
|
||||||
|
|
||||||
|
if( pxBlock->xBlockSize > xMaxSize )
|
||||||
|
{
|
||||||
|
xMaxSize = pxBlock->xBlockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( pxBlock->xBlockSize < xMinSize )
|
||||||
|
{
|
||||||
|
xMinSize = pxBlock->xBlockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move to the next block in the chain until the last block is
|
||||||
|
reached. */
|
||||||
|
pxBlock = pxBlock->pxNextFreeBlock;
|
||||||
|
} while( pxBlock != pxEnd );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xTaskResumeAll();
|
||||||
|
|
||||||
|
pxHeapStats->xSizeOfLargestFreeBlockInBytes = xMaxSize;
|
||||||
|
pxHeapStats->xSizeOfSmallestFreeBlockInBytes = xMinSize;
|
||||||
|
pxHeapStats->xNumberOfFreeBlocks = xBlocks;
|
||||||
|
|
||||||
|
taskENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
pxHeapStats->xAvailableHeapSpaceInBytes = xFreeBytesRemaining;
|
||||||
|
pxHeapStats->xNumberOfSuccessfulAllocations = xNumberOfSuccessfulAllocations;
|
||||||
|
pxHeapStats->xNumberOfSuccessfulFrees = xNumberOfSuccessfulFrees;
|
||||||
|
pxHeapStats->xMinimumEverFreeBytesRemaining = xMinimumEverFreeBytesRemaining;
|
||||||
|
}
|
||||||
|
taskEXIT_CRITICAL();
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
static void prvHeapInit( void )
|
static void prvHeapInit( void )
|
||||||
{
|
{
|
||||||
BlockLink_t *pxFirstFreeBlock;
|
BlockLink_t *pxFirstFreeBlock;
|
||||||
|
|
|
@ -116,10 +116,12 @@ static const size_t xHeapStructSize = ( sizeof( BlockLink_t ) + ( ( size_t ) ( p
|
||||||
/* Create a couple of list links to mark the start and end of the list. */
|
/* Create a couple of list links to mark the start and end of the list. */
|
||||||
static BlockLink_t xStart, *pxEnd = NULL;
|
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 calls to allocate and free memory as well as the
|
||||||
fragmentation. */
|
number of free bytes remaining, but says nothing about fragmentation. */
|
||||||
static size_t xFreeBytesRemaining = 0U;
|
static size_t xFreeBytesRemaining = 0U;
|
||||||
static size_t xMinimumEverFreeBytesRemaining = 0U;
|
static size_t xMinimumEverFreeBytesRemaining = 0U;
|
||||||
|
static size_t xNumberOfSuccessfulAllocations = 0;
|
||||||
|
static size_t xNumberOfSuccessfulFrees = 0;
|
||||||
|
|
||||||
/* Gets set to the top bit of an size_t type. When this bit in the xBlockSize
|
/* 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
|
member of an BlockLink_t structure is set then the block belongs to the
|
||||||
|
@ -231,6 +233,7 @@ void *pvReturn = NULL;
|
||||||
by the application and has no "next" block. */
|
by the application and has no "next" block. */
|
||||||
pxBlock->xBlockSize |= xBlockAllocatedBit;
|
pxBlock->xBlockSize |= xBlockAllocatedBit;
|
||||||
pxBlock->pxNextFreeBlock = NULL;
|
pxBlock->pxNextFreeBlock = NULL;
|
||||||
|
xNumberOfSuccessfulAllocations++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -301,6 +304,7 @@ BlockLink_t *pxLink;
|
||||||
xFreeBytesRemaining += pxLink->xBlockSize;
|
xFreeBytesRemaining += pxLink->xBlockSize;
|
||||||
traceFREE( pv, pxLink->xBlockSize );
|
traceFREE( pv, pxLink->xBlockSize );
|
||||||
prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
|
prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
|
||||||
|
xNumberOfSuccessfulFrees++;
|
||||||
}
|
}
|
||||||
( void ) xTaskResumeAll();
|
( void ) xTaskResumeAll();
|
||||||
}
|
}
|
||||||
|
@ -482,4 +486,56 @@ const HeapRegion_t *pxHeapRegion;
|
||||||
/* Work out the position of the top bit in a size_t variable. */
|
/* Work out the position of the top bit in a size_t variable. */
|
||||||
xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 );
|
xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 );
|
||||||
}
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortGetHeapStats( HeapStats_t *pxHeapStats )
|
||||||
|
{
|
||||||
|
BlockLink_t *pxBlock;
|
||||||
|
size_t xBlocks = 0, xMaxSize = 0, xMinSize = 0;
|
||||||
|
|
||||||
|
vTaskSuspendAll();
|
||||||
|
{
|
||||||
|
pxBlock = xStart.pxNextFreeBlock;
|
||||||
|
|
||||||
|
/* pxBlock will be NULL if the heap has not been initialised. The heap
|
||||||
|
is initialised automatically when the first allocation is made. */
|
||||||
|
if( pxBlock != NULL )
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
/* Increment the number of blocks and record the largest block seen
|
||||||
|
so far. */
|
||||||
|
xBlocks++;
|
||||||
|
|
||||||
|
if( pxBlock->xBlockSize > xMaxSize )
|
||||||
|
{
|
||||||
|
xMaxSize = pxBlock->xBlockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( pxBlock->xBlockSize < xMinSize )
|
||||||
|
{
|
||||||
|
xMinSize = pxBlock->xBlockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move to the next block in the chain until the last block is
|
||||||
|
reached. */
|
||||||
|
pxBlock = pxBlock->pxNextFreeBlock;
|
||||||
|
} while( pxBlock != pxEnd );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xTaskResumeAll();
|
||||||
|
|
||||||
|
pxHeapStats->xSizeOfLargestFreeBlockInBytes = xMaxSize;
|
||||||
|
pxHeapStats->xSizeOfSmallestFreeBlockInBytes = xMinSize;
|
||||||
|
pxHeapStats->xNumberOfFreeBlocks = xBlocks;
|
||||||
|
|
||||||
|
taskENTER_CRITICAL();
|
||||||
|
{
|
||||||
|
pxHeapStats->xAvailableHeapSpaceInBytes = xFreeBytesRemaining;
|
||||||
|
pxHeapStats->xNumberOfSuccessfulAllocations = xNumberOfSuccessfulAllocations;
|
||||||
|
pxHeapStats->xNumberOfSuccessfulFrees = xNumberOfSuccessfulFrees;
|
||||||
|
pxHeapStats->xMinimumEverFreeBytesRemaining = xMinimumEverFreeBytesRemaining;
|
||||||
|
}
|
||||||
|
taskEXIT_CRITICAL();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue