📄 avm_allo.c
字号:
{
MemBlockDesc_t *Block_p, *New_p = NULL, *Bot_p = NULL, *Top_p = NULL;
U32 BlockAlignedSize, ReAllocAlignedSize, AlignedSizeDifference, AddrAlignedSizeDifference;
U32 AligningMask, SizeAligningMask;
U32 Tmp;
#ifdef DEBUG_CODE
U32 ChangedSize;
void *ChangedStart;
void *BlockAddrBefore;
U32 BlockSizeBefore, BlockUserSizeBefore, BotSizeBefore;
U8 PreserveProbe;
#endif
BOOL EnlargeBelowForbidden = FALSE;
void *PreserveAddr_p;
U32 PreserveSize;
STAVMEM_AllocBlockParams_t AllocBlockParams;
stavmem_Partition_t *Partition_p;
ST_ErrorCode_t Err = ST_NO_ERROR;
/* Exit if bad parameter */
if ((BlockHandle_p == NULL) ||
(ReAllocBlockParams_p == NULL) ||
((ReAllocBlockParams_p->NumberOfForbiddenRanges > 0) && (ReAllocBlockParams_p->ForbiddenRangeArray_p == NULL)) ||
((ReAllocBlockParams_p->NumberOfForbiddenBorders > 0) && (ReAllocBlockParams_p->ForbiddenBorderArray_p == NULL)))
{
return(ST_ERROR_BAD_PARAMETER);
}
/* Get pointer to partition the block belongs to */
Partition_p = (stavmem_Partition_t *) ReAllocBlockParams_p->PartitionHandle;
/* Exit if the partition is not valid */
if (Partition_p->PartitionValidity != AVMEM_VALID_PARTITION)
{
return(STAVMEM_ERROR_INVALID_PARTITION_HANDLE);
}
/* Exit if bad parameter */
if ((ReAllocBlockParams_p->NumberOfForbiddenRanges > Partition_p->Device_p->MaxForbiddenRanges) ||
(ReAllocBlockParams_p->NumberOfForbiddenBorders > Partition_p->Device_p->MaxForbiddenBorders))
{
return(ST_ERROR_BAD_PARAMETER);
}
/* Exit if block handle is invalid */
if ((*BlockHandle_p == STAVMEM_INVALID_BLOCK_HANDLE) || (!stavmem_BlockHandleBelongsToSpace(*BlockHandle_p, *(Partition_p->Device_p))))
{
/* Bad block handle */
return(STAVMEM_ERROR_INVALID_BLOCK_HANDLE);
}
/* Setting pointer to block descriptor */
Block_p = (MemBlockDesc_t *) *BlockHandle_p;
#ifdef DEBUG_CODE
if ((((U32) Block_p->AlignedStartAddr_p) - ((U32) Block_p->StartAddr_p) + Block_p->UserSize) > Block_p->Size)
{
/* ErrorCase */
stavmem_BlockAndBip();
}
#endif
/* Exit if block is crossing any specified forbidden zone */
if (IsInForbiddenRangeOrBorder(Block_p->StartAddr_p, (void *) (((U32) Block_p->StartAddr_p) + Block_p->Size - 1),
ReAllocBlockParams_p->NumberOfForbiddenRanges, ReAllocBlockParams_p->ForbiddenRangeArray_p,
ReAllocBlockParams_p->NumberOfForbiddenBorders, ReAllocBlockParams_p->ForbiddenBorderArray_p))
{
return(STAVMEM_ERROR_BLOCK_IN_FORBIDDEN_ZONE);
}
/* Exit if block is not in partition */
if ((U32) (Block_p->PartitionHandle) != (U32) (Partition_p))
{
return(STAVMEM_ERROR_INVALID_PARTITION_HANDLE);
}
/* If first address of the block is a forbidden border, cannot cross it */
Tmp = 0;
while ((!EnlargeBelowForbidden) && (Tmp < ReAllocBlockParams_p->NumberOfForbiddenBorders))
{
/* Test if any forbidden border is the first address of the block. */
if (((U32) ReAllocBlockParams_p->ForbiddenBorderArray_p[Tmp]) == ((U32) Block_p->StartAddr_p))
{
EnlargeBelowForbidden = TRUE;
}
Tmp++;
}
#ifdef USE_SEMAPHORE
/* Wait for the allocations locking semaphore to be free */
semaphore_wait(&(Partition_p->Device_p->LockAllocSemaphore));
#endif
/* Mark forbidden zones to disable allocation on these zones */
Err = MarkForbiddenRangesAndBorders(Partition_p,
ReAllocBlockParams_p->NumberOfForbiddenRanges, ReAllocBlockParams_p->ForbiddenRangeArray_p,
ReAllocBlockParams_p->NumberOfForbiddenBorders, ReAllocBlockParams_p->ForbiddenBorderArray_p);
/* Process allocation if no errors in forbidden zones marking */
if (Err == ST_NO_ERROR)
{
/* Initialise variables */
BlockAlignedSize = Block_p->Size - (((U32) Block_p->AlignedStartAddr_p) - ((U32) Block_p->StartAddr_p));
PreserveAddr_p = Block_p->AlignedStartAddr_p;
PreserveSize = Block_p->UserSize;
#ifdef DEBUG_CODE
PreserveProbe = *((U8 *) PreserveAddr_p);
#endif
AligningMask = Block_p->Alignment - 1;
/* Adjust the size so the end address will be aligned */
/* Consequence: alloc 5 byte aligned on 8 will alloc 8 bytes ! */
if (AligningMask <= MAX_SIZE_ALIGNING_MASK)
{
SizeAligningMask = AligningMask;
}
else
{
SizeAligningMask = MAX_SIZE_ALIGNING_MASK;
}
ReAllocAlignedSize = (ReAllocBlockParams_p->Size + SizeAligningMask) & ~SizeAligningMask;
if (ReAllocAlignedSize < Block_p->UserSize)
{
/* The requested size is smaller and allows to reduce current block size */
AlignedSizeDifference = BlockAlignedSize - ReAllocAlignedSize;
AddrAlignedSizeDifference = (AlignedSizeDifference + AligningMask) & ~AligningMask;
if ((Block_p->BlockAbove_p != NULL) && (!Block_p->BlockAbove_p->IsUsed))
{
/* The block above is unused, so give it some more memory */
Block_p->Size -= AlignedSizeDifference;
Block_p->UserSize = ReAllocBlockParams_p->Size;
Block_p->BlockAbove_p->Size += AlignedSizeDifference;
Block_p->BlockAbove_p->StartAddr_p = (void *) (((U32) Block_p->BlockAbove_p->StartAddr_p) - AlignedSizeDifference);
#ifdef DEBUG_CODE
STTBX_Print(("****** Re-allocate with reduction on top.\n"));
if ((((U32) Block_p->AlignedStartAddr_p) - ((U32) Block_p->StartAddr_p) + Block_p->UserSize) > Block_p->Size)
{
/* ErrorCase */
stavmem_BlockAndBip();
}
#endif
/* Start address is unchanged: data is preserved, no need to copy it */
}
else if ((Block_p->BlockBelow_p != NULL) && (!Block_p->BlockBelow_p->IsUsed) &&
((((U32) Block_p->AlignedStartAddr_p) + AddrAlignedSizeDifference + ReAllocBlockParams_p->Size) <= (((U32) Block_p->StartAddr_p) + Block_p->Size)))
{
/* The block below is unused, so give it some more memory */
Block_p->Size -= AddrAlignedSizeDifference;
Block_p->UserSize = ReAllocBlockParams_p->Size;
Block_p->StartAddr_p = (void *) (((U32) Block_p->StartAddr_p) + AddrAlignedSizeDifference);
Block_p->AlignedStartAddr_p = (void *) (((U32) Block_p->AlignedStartAddr_p) + AddrAlignedSizeDifference);
#ifdef DEBUG_CODE
STTBX_Print(("****** Re-allocate with reduction on bottom.\n"));
if ((((U32) Block_p->AlignedStartAddr_p) - ((U32) Block_p->StartAddr_p) + Block_p->UserSize) > Block_p->Size)
{
/* ErrorCase */
stavmem_BlockAndBip();
}
#endif
Block_p->BlockBelow_p->Size += AddrAlignedSizeDifference;
/* Now copy data if required */
if (ReAllocBlockParams_p->PreserveData)
{
/* STAVMEM_CopyBlock1D(PreserveAddr_p, Block_p->AlignedStartAddr_p, Block_p->UserSize);*/
(*(ReAllocBlockParams_p->PreserveDataFunction)) (PreserveAddr_p, Block_p->AlignedStartAddr_p, Block_p->UserSize);
#ifdef DEBUG_CODE
if ((*(U8 *) Block_p->AlignedStartAddr_p) != PreserveProbe)
{
/* ErrorCase */
STTBX_Print(("****** PreserveData failed.\n"));
stavmem_BlockAndBip();
}
#endif
}
}
else
{
/* The blocks below and above are used or is the end of the list,
so create a new unused block for the memory left by the re-allocated block.
Allocate block structure */
New_p = AllocBlockDescriptor(&(Partition_p->Device_p->TopOfSpaceFreeBlocksList_p));
if (New_p == NULL)
{
/* Failed to allocate new block structure */
Err = STAVMEM_ERROR_MAX_BLOCKS;
}
else
{
/* Block structure allocation successful */
/* Reduce current block size */
Block_p->Size -= AlignedSizeDifference;
Block_p->UserSize = ReAllocBlockParams_p->Size;
/* Setup new block */
New_p->StartAddr_p = (void *) (((U32) Block_p->StartAddr_p) + Block_p->Size);
New_p->Size = AlignedSizeDifference;
New_p->IsUsed = FALSE;
/* Insert new unused block above block in partition blocks list */
InsertBlockAboveBlock(&(Partition_p->PartitionVeryTopBlock_p), New_p, Block_p);
/* Start address is unchanged: data is preserved, no need to copy it */
}
#ifdef DEBUG_CODE
STTBX_Print(("****** Re-allocate with reduction on top and free block creation.\n"));
if ((((U32) Block_p->AlignedStartAddr_p) - ((U32) Block_p->StartAddr_p) + Block_p->UserSize) > Block_p->Size)
{
/* ErrorCase */
stavmem_BlockAndBip();
}
#endif
}
}
else if (ReAllocAlignedSize > BlockAlignedSize)
{
/* The requested size is larger and requires enlargement of block or re-allocattion */
AlignedSizeDifference = ReAllocAlignedSize - BlockAlignedSize;
AddrAlignedSizeDifference = (AlignedSizeDifference + AligningMask) & ~AligningMask;
/* Consider blocks below and above */
Bot_p = Block_p->BlockBelow_p;
Top_p = Block_p->BlockAbove_p;
if ((Top_p != NULL) && (!Top_p->IsUsed) && (Top_p->Size >= AlignedSizeDifference))
{
/* Block above is unused and large enough: use part of it to enlarge block */
Block_p->Size += AlignedSizeDifference;
Block_p->UserSize = ReAllocBlockParams_p->Size;
#ifdef DEBUG_CODE
STTBX_Print(("****** Re-allocate with enlargment on top.\n"));
if ((((U32) Block_p->AlignedStartAddr_p) - ((U32) Block_p->StartAddr_p) + Block_p->UserSize) > Block_p->Size)
{
/* ErrorCase */
stavmem_BlockAndBip();
}
#endif
Top_p->StartAddr_p = (void *) (((U32) Top_p->StartAddr_p) + AlignedSizeDifference);
Top_p->Size -= AlignedSizeDifference;
if (Top_p->Size == 0)
{
/* The top unused block is now of zero size so remove it from partition list of blocks */
RemoveBlock(&(Partition_p->PartitionVeryTopBlock_p), &(Partition_p->PartitionVeryBottomBlock_p), Top_p);
/* Free off block structure */
FreeBlockDescriptor(&(Partition_p->Device_p->TopOfSpaceFreeBlocksList_p), Top_p);
}
/* Start address is unchanged: data is preserved, no need to copy it */
}
else if ((!EnlargeBelowForbidden) && (Bot_p != NULL) && (!Bot_p->IsUsed) && /* can enlarge below and block below is free and */
((((U32) Block_p->AlignedStartAddr_p) - AddrAlignedSizeDifference) >= ((U32) Bot_p->StartAddr_p)))
{
/* Block below is unused: use part of it. */
#ifdef DEBUG_CODE
ChangedSize = (AddrAlignedSizeDifference - (((U32) Block_p->AlignedStartAddr_p) - ((U32) Block_p->StartAddr_p)));
ChangedStart = Block_p->StartAddr_p;
BlockAddrBefore = Block_p->AlignedStartAddr_p;
BlockSizeBefore = Block_p->Size;
BlockUserSizeBefore = Block_p->UserSize;
BotSizeBefore = Bot_p->Size;
#endif
Bot_p->Size -= (AddrAlignedSizeDifference - (((U32) Block_p->AlignedStartAddr_p) - ((U32) Block_p->StartAddr_p)));
Block_p->Size += (AddrAlignedSizeDifference - (((U32) Block_p->AlignedStartAddr_p) - ((U32) Block_p->StartAddr_p)));
Block_p->UserSize = ReAllocBlockParams_p->Size;
Block_p->StartAddr_p = (void *) (((U32) Bot_p->StartAddr_p) + Bot_p->Size);
Block_p->AlignedStartAddr_p = (void *) (((U32) Block_p->AlignedStartAddr_p) - AddrAlignedSizeDifference);
#ifdef DEBUG_CODE
STTBX_Print(("****** Re-allocate with enlargment on bottom.\n"));
if ((((U32) Block_p->AlignedStartAddr_p) - ((U32) Block_p->StartAddr_p) + Block_p->UserSize) > Block_p->Size)
{
/* ErrorCase */
stavmem_BlockAndBip();
}
#endif
if (Bot_p->Size == 0)
{
/* The below unused block is now of zero size so remove it from partition list of blocks */
RemoveBlock(&(Partition_p->PartitionVeryTopBlock_p), &(Partition_p->PartitionVeryBottomBlock_p), Bot_p);
/* Free off block structure */
FreeBlockDescriptor(&(Partition_p->Device_p->TopOfSpaceFreeBlocksList_p), Bot_p);
}
/* Now copy data if required */
if (ReAllocBlockParams_p->PreserveData)
{
/* STAVMEM_CopyBlock1D(PreserveAddr_p, Block_p->AlignedStartAddr_p, PreserveSize);*/
(*(ReAllocBlockParams_p->PreserveDataFunction)) (PreserveAddr_p, Block_p->AlignedStartAddr_p, PreserveSize);
#ifdef DEBUG_CODE
if ((*(U8 *) Block_p->AlignedStartAddr_p) != PreserveProbe)
{
/* ErrorCase */
STTBX_Print(("****** PreserveData failed.\n"));
stavmem_BlockAndBip();
}
#endif
}
}
else
{
#ifdef DEBUG_CODE
STTBX_Print(("****** Re-allocate with enlargment by Allocate and Free.\n"));
#endif
/* Need more space but blocks above and below are not large
enough: re-allocate block somewhere else and free the current place */
AllocBlockParams.Size = ReAllocBlockParams_p->Size;
AllocBlockParams.Alignment = Block_p->Alignment;
AllocBlockParams.AllocMode = Block_p->AllocMode;
AllocBlockParams.PartitionHandle = Block_p->PartitionHandle;
AllocBlockParams.NumberOfForbiddenRanges = ReAllocBlockParams_p->NumberOfForbiddenRanges;
AllocBlockParams.ForbiddenRangeArray_p = ReAllocBlockParams_p->ForbiddenRangeArray_p;
AllocBlockParams.NumberOfForbiddenBorders = ReAllocBlockParams_p->NumberOfForbiddenBorders;
AllocBlockParams.ForbiddenBorderArray_p = ReAllocBlockParams_p->ForbiddenBorderArray_p;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -