在freertos中没有对realloc重分配内存函数进行支持,在此记录自己的实现方法。
void* pvPortRealloc(void* pv, size_t xWantedSize)
{
void* pvReturn = NULL;
if (xWantedSize == 0)
{
vPortFree(pv);
}
else if(xWantedSize > 0)
{
if (pv == NULL)
{
return pvPortMalloc(xWantedSize);
}
else
{
size_t xAdditionalRequiredSize;
uint8_t* puc = (uint8_t*)pv;
BlockLink_t* pxLink;
size_t xExpansionSize; //需要扩充的大小
size_t xRealSize; //真实大小
puc -= xHeapStructSize;
pxLink = (void*)puc;//获取当前块信息
xAdditionalRequiredSize = xHeapStructSize + portBYTE_ALIGNMENT - (xWantedSize & portBYTE_ALIGNMENT_MASK);
if (heapADD_WILL_OVERFLOW(xWantedSize, xAdditionalRequiredSize) == 0)
{
xWantedSize += xAdditionalRequiredSize;
}
else
{
xWantedSize = 0;
}
if (heapBLOCK_SIZE_IS_VALID(xWantedSize) != 0)
{
xRealSize = pxLink->xBlockSize & ~heapBLOCK_ALLOCATED_BITMASK;//获取到真实大小
vTaskSuspendAll();
if (xWantedSize == xRealSize)//在分配内存时会分配4字节对齐的空间,所以可能存在不用扩充的情况
{
pvReturn = pv;
}
else if(xWantedSize > xRealSize)//扩充内存
{
xExpansionSize = xWantedSize - xRealSize;//计算需要扩充大小
//如果堆剩余大小大于扩展大小那么检查前后连续的空闲堆
if (xExpansionSize <= xFreeBytesRemaining)
{
BlockLink_t* pxPreviousBlock, * pxIterator, * pxNewBlockLink = NULL;
BlockLink_t* pxBlock = NULL, * pxPreviousBlock1 = NULL;
for (pxPreviousBlock = pxIterator = &xStart; pxIterator->pxNextFreeBlock != NULL && pxIterator->pxNextFreeBlock < pxLink; pxIterator = pxIterator->pxNextFreeBlock)
{
pxPreviousBlock = pxIterator;
if (pxBlock == NULL && pxIterator->pxNextFreeBlock ->xBlockSize >= xWantedSize)
{
pxPreviousBlock1 = pxIterator;
pxBlock = pxIterator->pxNextFreeBlock;
}
}
//检查后面一个空闲块是否满足扩展条件
if ((BlockLink_t*)(puc + xRealSize) == pxIterator->pxNextFreeBlock && pxIterator->pxNextFreeBlock->xBlockSize >= xExpansionSize)
{
pvReturn = pv;
// 如果后面一个块的空间在分配后小于管理块大小,直接从链表中删除
if (pxIterator->pxNextFreeBlock->xBlockSize - xExpansionSize < xHeapStructSize)
{
pxNewBlockLink = pxLink;
pxNewBlockLink->xBlockSize = xRealSize + pxIterator->pxNextFreeBlock->xBlockSize;
pxIterator->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock;
}
else// 如果后面一个块的空间在分配后大于管理块大小,创建新块
{
pxNewBlockLink = (BlockLink_t*)(puc + xWantedSize);
BlockLink_t* temp = pxIterator->pxNextFreeBlock->pxNextFreeBlock;
pxNewBlockLink->xBlockSize = pxIterator->pxNextFreeBlock->xBlockSize - xExpansionSize;//设置新块大小
pxNewBlockLink->pxNextFreeBlock = temp;
pxIterator->pxNextFreeBlock = pxNewBlockLink;
pxNewBlockLink = pxLink;
pxNewBlockLink->xBlockSize = xWantedSize;
}
xFreeBytesRemaining -= pxNewBlockLink->xBlockSize - xRealSize;
}
else if ((BlockLink_t*)((uint8_t*)pxIterator + pxIterator->xBlockSize) == pxLink && pxIterator->xBlockSize >= xExpansionSize)//检查前面一个空闲块是否满足条件
{
puc -= xExpansionSize;
if ((BlockLink_t*)puc == pxIterator)//要扩展的大小等于前面的块大小,合并两个块
{
pxPreviousBlock->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
pxNewBlockLink = pxIterator;
pxNewBlockLink->xBlockSize = xWantedSize;
}
else if (pxIterator->xBlockSize - xExpansionSize >= xHeapStructSize)//扩充后前面的块的大小足够创建新块,创建块
{
pxIterator->xBlockSize -= xExpansionSize;
pxNewBlockLink = (BlockLink_t*)puc;
pxNewBlockLink->xBlockSize = xWantedSize;
}
else//扩展后前面的块剩余大小不足创建新块,合并块
{
pxPreviousBlock->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
pxNewBlockLink = pxIterator;
pxNewBlockLink->xBlockSize += xRealSize;
}
pvReturn = (uint8_t*)pxNewBlockLink + xHeapStructSize;
xFreeBytesRemaining -= pxNewBlockLink->xBlockSize - xRealSize;
memcpy(pvReturn, pv, xRealSize - xHeapStructSize);
}
if (pvReturn == NULL)
{
// 判断上一次遍历时是否找到符合的块,如果没有找到接着上一次中断的地方找
if (pxBlock == NULL && xWantedSize < xFreeBytesRemaining && pxPreviousBlock != NULL)
{
pxBlock = pxPreviousBlock->pxNextFreeBlock;
while ((pxBlock->xBlockSize < xWantedSize) && (pxBlock->pxNextFreeBlock != NULL))
{
pxPreviousBlock = pxBlock;
pxBlock = pxBlock->pxNextFreeBlock;
}
}
else
{
pxPreviousBlock = pxPreviousBlock1;
}
if (pxBlock != NULL)
{
pvReturn = (void*)((uint8_t*)pxBlock + xHeapStructSize);
//如果块剩余的内存大于等于管理结构体大小就创建新块
if (pxBlock->xBlockSize - xWantedSize >= xHeapStructSize)
{
pxNewBlockLink = (BlockLink_t*)((uint8_t*)pxBlock + xWantedSize);
pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
pxNewBlockLink->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
pxBlock->xBlockSize = xWantedSize;
}
else//如果本块剩余的空间小于管理结构体的大小
{
pxNewBlockLink = pxBlock->pxNextFreeBlock;
}
pxPreviousBlock->pxNextFreeBlock = pxNewBlockLink;
xFreeBytesRemaining -= pxBlock->xBlockSize;
pxNewBlockLink = pxBlock;
memcpy(pvReturn, pv, xRealSize - xHeapStructSize);
vPortFree(pv);
}
}
if (pxNewBlockLink != NULL)
{
pxNewBlockLink->pxNextFreeBlock = NULL;
//memset((uint8_t*)pvReturn + xRealSize - xHeapStructSize, 0, pxNewBlockLink->xBlockSize - xRealSize);
heapALLOCATE_BLOCK(pxNewBlockLink);
xNumberOfSuccessfulAllocations++;
if (xFreeBytesRemaining < xMinimumEverFreeBytesRemaining)
{
xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
}
}
}
/* else
{
mtCOVERAGE_TEST_MARKER();
}*/
}
else if (xWantedSize < xRealSize)//减小内存,一般来说一定会成功分配
{
xExpansionSize = xRealSize - xWantedSize;//计算需要缩减大小
pvReturn = pv;
if (xExpansionSize > xHeapStructSize)//释放的内存可以创建管理块
{
BlockLink_t* pxIterator, * pxNewBlockLink = NULL;
for (pxIterator = &xStart; pxIterator->pxNextFreeBlock != NULL && pxIterator->pxNextFreeBlock < pxLink; pxIterator = pxIterator->pxNextFreeBlock)
{
//if (pxBlock == NULL && pxIterator->xBlockSize == xWantedSize)//有相等的也记录下来,防止内存碎片
//{
// pxBlock = pxIterator;
//}
}
//如果前面的块空闲合并过去,防止内存碎片
// if()
//直接截断后面部分,最简单的方法,但可能会导致内存碎片过多
pxNewBlockLink = (BlockLink_t*)((uint8_t*)pxLink + xWantedSize);
if ((BlockLink_t*)((uint8_t*)pxNewBlockLink + xExpansionSize) == pxIterator->pxNextFreeBlock && pxIterator->pxNextFreeBlock != pxEnd)
{
pxNewBlockLink->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock;
pxNewBlockLink->xBlockSize = xExpansionSize + pxIterator->pxNextFreeBlock->xBlockSize;
}
else
{
pxNewBlockLink->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
pxNewBlockLink->xBlockSize = xExpansionSize;
}
pxIterator->pxNextFreeBlock = pxNewBlockLink;
pxLink->xBlockSize = xWantedSize;
heapALLOCATE_BLOCK(pxLink);
xFreeBytesRemaining += xExpansionSize;
}
}
xTaskResumeAll();
}
/* else
{
mtCOVERAGE_TEST_MARKER();
}*/
}
}
return pvReturn;
}