2024-01-14 11:28:45 +00:00
# include "mm.h"
/*<2A> 鲻̫С */
# define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize << 1 ) )
/* Assumes 8bit bytes!<21> <> <EFBFBD> <EFBFBD> Ϊ8λ */
# define heapBITS_PER_BYTE ( ( size_t ) 8 )
/* Max value that fits in a size_t type. size_t<5F> <74> <EFBFBD> <EFBFBD> ֵ */
# define heapSIZE_MAX ( ~( ( size_t ) 0 ) )
/* Check if multiplying a and b will result in overflow. <20> <> <EFBFBD> <EFBFBD> a <20> <> B <20> <> <EFBFBD> <EFBFBD> <EFBFBD> Ƿ<EFBFBD> <C7B7> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> */
# define heapMULTIPLY_WILL_OVERFLOW( a, b ) ( ( ( a ) > 0 ) && ( ( b ) > ( heapSIZE_MAX / ( a ) ) ) )
/* Check if adding a and b will result in overflow. <20> <> <EFBFBD> <EFBFBD> a <20> <> b<EFBFBD> <62> <EFBFBD> <EFBFBD> <EFBFBD> Ƿ<EFBFBD> <C7B7> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> */
# define heapADD_WILL_OVERFLOW( a, b ) ( ( a ) > ( heapSIZE_MAX - ( b ) ) )
/* BlockLink_t<5F> ṹ<EFBFBD> е <EFBFBD> xBlockSize<7A> <65> Ա<EFBFBD> <D4B1> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> Чλ<D0A7> <CEBB> MSB<53> <42> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ٿ<EFBFBD> <D9BF> ķ<EFBFBD> <C4B7> <EFBFBD> ״̬<D7B4> <CCAC>
<EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> BlockLink_t <EFBFBD> ṹ <EFBFBD> е <EFBFBD> xBlockSize <EFBFBD> <EFBFBD> Ա <EFBFBD> <EFBFBD> MSBʱ <EFBFBD> <EFBFBD> <EFBFBD> ÿ 鱻 <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> Ӧ <EFBFBD> ó <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
<EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> λ Ϊ <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ʱ <EFBFBD> <EFBFBD> <EFBFBD> ÿ <EFBFBD> <EFBFBD> <EFBFBD> Ȼ <EFBFBD> ǿ <EFBFBD> <EFBFBD> ж ѿ ռ <EFBFBD> <EFBFBD> <EFBFBD> һ <EFBFBD> <EFBFBD> <EFBFBD> ֡ <EFBFBD> */
# define heapBLOCK_ALLOCATED_BITMASK ( ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 ) ) //<2F> ڴ<EFBFBD> <DAB4> <EFBFBD> <EFBFBD> <EFBFBD> ʹ <EFBFBD> <CAB9>
# define heapBLOCK_SIZE_IS_VALID( xBlockSize ) ( ( ( xBlockSize ) & heapBLOCK_ALLOCATED_BITMASK ) == 0 )
# define heapBLOCK_IS_ALLOCATED( pxBlock ) ( ( ( pxBlock->xBlockSize ) & heapBLOCK_ALLOCATED_BITMASK ) != 0 )
# define heapALLOCATE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) |= heapBLOCK_ALLOCATED_BITMASK )
# define heapFREE_BLOCK( pxBlock ) ( ( pxBlock->xBlockSize ) &= ~heapBLOCK_ALLOCATED_BITMASK )
static uint8_t ucHeap [ configTOTAL_HEAP_SIZE ] ; //<2F> <> <EFBFBD> ڴ<EFBFBD> <DAB4> <EFBFBD> С <EFBFBD> <D0A1> <EFBFBD> <EFBFBD>
typedef struct A_BLOCK_LINK
{
struct A_BLOCK_LINK * pxNextFreeBlock ; /*<< The next free block in the list. <20> <> һ <EFBFBD> <D2BB> <EFBFBD> <EFBFBD> <EFBFBD> п<EFBFBD> */
size_t xBlockSize ; /*<< The size of the free block.<2E> <> <EFBFBD> п<EFBFBD> <D0BF> Ĵ<EFBFBD> С */
} BlockLink_t ;
/* <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ͷŵ<CDB7> <C5B5> ڴ<EFBFBD> <DAB4> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> 뵽<EFBFBD> <EBB5BD> <EFBFBD> <EFBFBD> <EFBFBD> ڴ<EFBFBD> <DAB4> <EFBFBD> <EFBFBD> б <EFBFBD> <D0B1> е <EFBFBD> <D0B5> <EFBFBD> ȷλ<C8B7> á<EFBFBD>
<EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ڴ <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ˴ <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ڣ <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ͷ ŵ Ŀ 齫 <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ǰ <EFBFBD> <EFBFBD> <EFBFBD> Ŀ <EFBFBD> <EFBFBD> <EFBFBD> / <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> Ŀ <EFBFBD> <EFBFBD> ϲ <EFBFBD> <EFBFBD> <EFBFBD> */
static void prvInsertBlockIntoFreeList ( BlockLink_t * pxBlockToInsert ) ;
static void prvHeapInit ( void ) ;
/* λ<> <CEBB> ÿ<EFBFBD> <C3BF> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ڴ<EFBFBD> <DAB4> 鿪ͷ<E9BFAA> Ľṹ<C4BD> Ĵ<EFBFBD> С <EFBFBD> <D0A1> <EFBFBD> 밴<EFBFBD> <EBB0B4> ȷ<EFBFBD> <C8B7> <EFBFBD> ֽڶ<D6BD> <DAB6> 롣 */
static const size_t xHeapStructSize = ( sizeof ( BlockLink_t ) + ( ( size_t ) ( portBYTE_ALIGNMENT - 1 ) ) ) & ~ ( ( size_t ) portBYTE_ALIGNMENT_MASK ) ;
/* <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> б <EFBFBD> <D0B1> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> б <EFBFBD> <D0B1> Ŀ<EFBFBD> ʼ <EFBFBD> ͽ<EFBFBD> <CDBD> <EFBFBD> <EFBFBD> <EFBFBD> */
static BlockLink_t xStart ;
static BlockLink_t * pxEnd = NULL ; //<2F> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> NULL<4C> <4C> <EFBFBD> <EFBFBD> <EFBFBD> Ѿ<EFBFBD> <D1BE> <EFBFBD> ʼ <EFBFBD> <CABC> <EFBFBD> <EFBFBD> <EFBFBD> ڴ<EFBFBD> <DAB4> <EFBFBD> ,<2C> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> Ҫ
/* <20> <> <EFBFBD> ٷ<EFBFBD> <D9B7> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ͷ<EFBFBD> <CDB7> ڴ<EFBFBD> <DAB4> ĵ<EFBFBD> <C4B5> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> Լ<EFBFBD> ʣ<EFBFBD> <CAA3> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ֽ<EFBFBD> <D6BD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> û<EFBFBD> <C3BB> ˵<EFBFBD> <CBB5> <EFBFBD> <EFBFBD> Ƭ<EFBFBD> <C6AC> * / */
static size_t xFreeBytesRemaining = 0U ;
static size_t xMinimumEverFreeBytesRemaining = 0U ;
static size_t xNumberOfSuccessfulAllocations = 0 ;
static size_t xNumberOfSuccessfulFrees = 0 ;
/*-----------------------------------------------------------*/
void * pvPortMalloc ( size_t xWantedSize )
{
BlockLink_t * pxBlock ;
BlockLink_t * pxPreviousBlock ;
BlockLink_t * pxNewBlockLink ;
void * pvReturn = NULL ;
size_t xAdditionalRequiredSize ;
{
/* If this is the first call to malloc then the heap will require
* initialisation to setup the list of free blocks . */
if ( pxEnd = = NULL )
{
prvHeapInit ( ) ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
if ( xWantedSize > 0 )
{
/* The wanted size must be increased so it can contain a BlockLink_t
* structure in addition to the requested amount of bytes . Some
* additional increment may also be needed for alignment . */
xAdditionalRequiredSize = xHeapStructSize + portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ;
if ( heapADD_WILL_OVERFLOW ( xWantedSize , xAdditionalRequiredSize ) = = 0 )
{
xWantedSize + = xAdditionalRequiredSize ;
}
else
{
xWantedSize = 0 ;
}
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
/* Check the block size we are trying to allocate is not so large that the
* top bit is set . The top bit of the block size member of the BlockLink_t
* structure is used to determine who owns the block - the application or
* the kernel , so it must be free . */
if ( heapBLOCK_SIZE_IS_VALID ( xWantedSize ) ! = 0 )
{
if ( ( xWantedSize > 0 ) & & ( xWantedSize < = xFreeBytesRemaining ) )
{
/* Traverse the list from the start (lowest address) block until
* one of adequate size is found . */
pxPreviousBlock = & xStart ;
pxBlock = xStart . pxNextFreeBlock ;
while ( ( pxBlock - > xBlockSize < xWantedSize ) & & ( pxBlock - > pxNextFreeBlock ! = NULL ) )
{
pxPreviousBlock = pxBlock ;
pxBlock = pxBlock - > pxNextFreeBlock ;
}
/* If the end marker was reached then a block of adequate size
* was not 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 ) + xHeapStructSize ) ;
/* 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 ) ;
configASSERT ( ( ( ( size_t ) pxNewBlockLink ) & portBYTE_ALIGNMENT_MASK ) = = 0 ) ;
/* Calculate the sizes of two blocks split from the
* single block . */
pxNewBlockLink - > xBlockSize = pxBlock - > xBlockSize - xWantedSize ;
pxBlock - > xBlockSize = xWantedSize ;
/* Insert the new block into the list of free blocks. */
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 . */
heapALLOCATE_BLOCK ( pxBlock ) ;
pxBlock - > pxNextFreeBlock = NULL ;
xNumberOfSuccessfulAllocations + + ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
traceMALLOC ( pvReturn , xWantedSize ) ;
}
configASSERT ( ( ( ( size_t ) pvReturn ) & ( size_t ) portBYTE_ALIGNMENT_MASK ) = = 0 ) ;
return pvReturn ;
}
/*-----------------------------------------------------------*/
void vPortFree ( void * pv )
{
uint8_t * puc = ( uint8_t * ) pv ;
BlockLink_t * pxLink ;
if ( pv ! = NULL )
{
/* The memory being freed will have an BlockLink_t structure immediately
* before it . */
puc - = xHeapStructSize ;
/* This casting is to keep the compiler from issuing warnings. */
pxLink = ( void * ) puc ;
configASSERT ( heapBLOCK_IS_ALLOCATED ( pxLink ) ! = 0 ) ;
configASSERT ( pxLink - > pxNextFreeBlock = = NULL ) ;
if ( heapBLOCK_IS_ALLOCATED ( pxLink ) ! = 0 )
{
if ( pxLink - > pxNextFreeBlock = = NULL )
{
/* The block is being returned to the heap - it is no longer
* allocated . */
heapFREE_BLOCK ( pxLink ) ;
# if ( configHEAP_CLEAR_MEMORY_ON_FREE == 1 )
{
( void ) memset ( puc + xHeapStructSize , 0 , pxLink - > xBlockSize - xHeapStructSize ) ;
}
# endif
{
/* Add this block to the list of free blocks. */
xFreeBytesRemaining + = pxLink - > xBlockSize ;
traceFREE ( pv , pxLink - > xBlockSize ) ;
prvInsertBlockIntoFreeList ( ( ( BlockLink_t * ) pxLink ) ) ;
xNumberOfSuccessfulFrees + + ;
}
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
}
/*-----------------------------------------------------------*/
size_t xPortGetFreeHeapSize ( void )
{
return xFreeBytesRemaining ;
}
/*-----------------------------------------------------------*/
size_t xPortGetMinimumEverFreeHeapSize ( void )
{
return xMinimumEverFreeBytesRemaining ;
}
/*-----------------------------------------------------------*/
void vPortInitialiseBlocks ( void )
{
/* This just exists to keep the linker quiet. */
}
/*-----------------------------------------------------------*/
void * pvPortCalloc ( size_t xNum ,
size_t xSize )
{
void * pv = NULL ;
if ( heapMULTIPLY_WILL_OVERFLOW ( xNum , xSize ) = = 0 )
{
pv = pvPortMalloc ( xNum * xSize ) ;
if ( pv ! = NULL )
{
( void ) memset ( pv , 0 , xNum * xSize ) ;
}
}
return pv ;
}
/*-----------------------------------------------------------*/
static void prvHeapInit ( void ) /* PRIVILEGED_FUNCTION */
{
BlockLink_t * pxFirstFreeBlock ;
uint8_t * pucAlignedHeap ;
portPOINTER_SIZE_TYPE uxAddress ;
size_t xTotalHeapSize = configTOTAL_HEAP_SIZE ;
/* Ensure the heap starts on a correctly aligned boundary. */
uxAddress = ( portPOINTER_SIZE_TYPE ) ucHeap ;
if ( ( uxAddress & portBYTE_ALIGNMENT_MASK ) ! = 0 )
{
uxAddress + = ( portBYTE_ALIGNMENT - 1 ) ;
uxAddress & = ~ ( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ;
xTotalHeapSize - = uxAddress - ( portPOINTER_SIZE_TYPE ) ucHeap ;
}
pucAlignedHeap = ( uint8_t * ) uxAddress ;
/* xStart is used to hold a pointer to the first item in the list of free
* blocks . The void cast is used to prevent compiler warnings . */
xStart . pxNextFreeBlock = ( void * ) pucAlignedHeap ;
xStart . xBlockSize = ( size_t ) 0 ;
/* pxEnd is used to mark the end of the list of free blocks and is inserted
* at the end of the heap space . */
uxAddress = ( ( portPOINTER_SIZE_TYPE ) pucAlignedHeap ) + xTotalHeapSize ;
uxAddress - = xHeapStructSize ;
uxAddress & = ~ ( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ;
pxEnd = ( BlockLink_t * ) uxAddress ;
pxEnd - > xBlockSize = 0 ;
pxEnd - > pxNextFreeBlock = NULL ;
/* To start with there is a single free block that is sized to take up the
* entire heap space , minus the space taken by pxEnd . */
pxFirstFreeBlock = ( BlockLink_t * ) pucAlignedHeap ;
pxFirstFreeBlock - > xBlockSize = ( size_t ) ( uxAddress - ( portPOINTER_SIZE_TYPE ) pxFirstFreeBlock ) ;
pxFirstFreeBlock - > pxNextFreeBlock = pxEnd ;
/* Only one block exists - and it covers the entire usable heap space. */
xMinimumEverFreeBytesRemaining = pxFirstFreeBlock - > xBlockSize ;
xFreeBytesRemaining = pxFirstFreeBlock - > xBlockSize ;
}
/*-----------------------------------------------------------*/
static void prvInsertBlockIntoFreeList ( BlockLink_t * pxBlockToInsert ) /* PRIVILEGED_FUNCTION */
{
BlockLink_t * pxIterator ;
uint8_t * puc ;
/* Iterate through the list until a block is found that has a higher address
* than the block being inserted . */
for ( pxIterator = & xStart ; pxIterator - > pxNextFreeBlock < pxBlockToInsert ; pxIterator = pxIterator - > pxNextFreeBlock )
{
/* Nothing to do here, just iterate to the right position. */
}
/* Do the block being inserted, and the block it is being inserted after
* make a contiguous block of memory ? */
puc = ( uint8_t * ) pxIterator ;
if ( ( puc + pxIterator - > xBlockSize ) = = ( uint8_t * ) pxBlockToInsert )
{
pxIterator - > xBlockSize + = pxBlockToInsert - > xBlockSize ;
pxBlockToInsert = pxIterator ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
/* Do the block being inserted, and the block it is being inserted before
* make a contiguous block of memory ? */
puc = ( uint8_t * ) pxBlockToInsert ;
if ( ( puc + pxBlockToInsert - > xBlockSize ) = = ( uint8_t * ) pxIterator - > pxNextFreeBlock )
{
if ( pxIterator - > pxNextFreeBlock ! = pxEnd )
{
/* Form one big block from the two blocks. */
pxBlockToInsert - > xBlockSize + = pxIterator - > pxNextFreeBlock - > xBlockSize ;
pxBlockToInsert - > pxNextFreeBlock = pxIterator - > pxNextFreeBlock - > pxNextFreeBlock ;
}
else
{
pxBlockToInsert - > pxNextFreeBlock = pxEnd ;
}
}
else
{
pxBlockToInsert - > pxNextFreeBlock = pxIterator - > pxNextFreeBlock ;
}
/* If the block being inserted plugged a gab, so was merged with the block
* before and the block after , then it ' s pxNextFreeBlock pointer will have
* already been set , and should not be set here as that would make it point
* to itself . */
if ( pxIterator ! = pxBlockToInsert )
{
pxIterator - > pxNextFreeBlock = pxBlockToInsert ;
}
else
{
mtCOVERAGE_TEST_MARKER ( ) ;
}
}
/*-----------------------------------------------------------*/
void vPortGetHeapStats ( HeapStats_t * pxHeapStats )
{
BlockLink_t * pxBlock ;
size_t xBlocks = 0 , xMaxSize = 0 , xMinSize = portMAX_DELAY ; /* portMAX_DELAY used as a portable way of getting the maximum value. */
{
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 )
{
while ( pxBlock ! = pxEnd )
{
/* 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 ;
}
}
}
pxHeapStats - > xSizeOfLargestFreeBlockInBytes = xMaxSize ;
pxHeapStats - > xSizeOfSmallestFreeBlockInBytes = xMinSize ;
pxHeapStats - > xNumberOfFreeBlocks = xBlocks ;
{
pxHeapStats - > xAvailableHeapSpaceInBytes = xFreeBytesRemaining ;
pxHeapStats - > xNumberOfSuccessfulAllocations = xNumberOfSuccessfulAllocations ;
pxHeapStats - > xNumberOfSuccessfulFrees = xNumberOfSuccessfulFrees ;
pxHeapStats - > xMinimumEverFreeBytesRemaining = xMinimumEverFreeBytesRemaining ;
}
}
/*-----------------------------------------------------------*/