📄 avm_allo.c
字号:
}
/* Get pointer to partition the block belongs to */
Partition_p = (stavmem_Partition_t *) AllocBlockParams_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 ((AllocBlockParams_p->NumberOfForbiddenRanges > Partition_p->Device_p->MaxForbiddenRanges) ||
(AllocBlockParams_p->NumberOfForbiddenBorders > Partition_p->Device_p->MaxForbiddenBorders))
{
return(ST_ERROR_BAD_PARAMETER);
}
/* Check counter of user-used blocks: if MaxUsedBlocks reached, cannot allocate more */
if (Partition_p->Device_p->CurrentlyUsedBlocks >= Partition_p->Device_p->MaxUsedBlocks)
{
/* Not allowed to allocate more block */
return(STAVMEM_ERROR_MAX_BLOCKS);
}
#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,
AllocBlockParams_p->NumberOfForbiddenRanges, AllocBlockParams_p->ForbiddenRangeArray_p,
AllocBlockParams_p->NumberOfForbiddenBorders, AllocBlockParams_p->ForbiddenBorderArray_p);
/* Process allocation if no errors in forbidden zones marking */
if (Err == ST_NO_ERROR)
{
Err = AllocBlockNoSemaphore(AllocBlockParams_p, BlockHandle_p);
}
/* Unmark forbidden zones now that allocation is done */
UnMarkForbiddenRangesAndBorders(Partition_p);
#ifdef USE_SEMAPHORE
/* Free the allocations locking semaphore */
semaphore_signal(&(Partition_p->Device_p->LockAllocSemaphore));
#endif
return(Err);
}
/*******************************************************************************
Name : AllocBlockNoSemaphore
Description : Internal function to allocate block, not semaphore protected
Used in STAVMEM_AllocBlock() and STAVMEM_ReAllocBlock()
Parameters : parameters pointers not NULL
Assumptions :
Limitations :
Returns : ST_NO_ERROR if success, STAVMEM_ERROR_PARTITION_FULL or
STAVMEM_ERROR_MAX_BLOCKS otherwise
*******************************************************************************/
ST_ErrorCode_t AllocBlockNoSemaphore(const STAVMEM_AllocBlockParams_t *AllocBlockParams_p, STAVMEM_BlockHandle_t *BlockHandle_p)
{
MemBlockDesc_t *Cur_p, *New_p = NULL;
void *CurrentStartAddr_p, *CurrentAlignedStartAddr_p;
U32 TotalSize, AlignedSize;
U32 Alignment = AllocBlockParams_p->Alignment;
U32 AligningMask, SizeAligningMask;
stavmem_Partition_t *Partition_p;
ST_ErrorCode_t Err = ST_NO_ERROR;
/* Get pointer to partition the block belongs to */
Partition_p = (stavmem_Partition_t *) AllocBlockParams_p->PartitionHandle;
/* Initialise variables */
RoundUpAlignment(&Alignment);
AligningMask = 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;
}
AlignedSize = (AllocBlockParams_p->Size + SizeAligningMask) & ~SizeAligningMask;
if (AllocBlockParams_p->AllocMode == STAVMEM_ALLOC_MODE_TOP_BOTTOM)
{
/* Search for an unused memory block of size greater than "size" */
Cur_p = Partition_p->PartitionVeryTopBlock_p;
while (Cur_p != NULL)
{
#ifdef DO_NOT_ALLOW_AREAS_CROSSING
/* Don't allow the areas to cross each other */
if (Cur_p->IsUsed && (Cur_p->AllocMode != STAVMEM_ALLOC_MODE_TOP_BOTTOM) && (Cur_p->AllocMode != STAVMEM_ALLOC_MODE_RESERVED) && (Cur_p->AllocMode != STAVMEM_ALLOC_MODE_FORBIDDEN))
{
/* Another area is reached: end search unsucessfully */
Cur_p = NULL;
break;
}
#endif
/* Check for a large enough unused block (size 0 means full range so it is enough for sure) */
/* if ((!Cur_p->IsUsed) && (Cur_p->Size >= AlignedSize))*/
if ((!Cur_p->IsUsed) && ((Cur_p->Size >= AlignedSize) || (Cur_p->Size == 0)))
{
/* Block is large enough before alignment, ensure it is still
large enough with alignment constraints */
CurrentStartAddr_p = (void *) (((U32) Cur_p->StartAddr_p) + Cur_p->Size - AlignedSize);
CurrentAlignedStartAddr_p = (void *) (((U32) CurrentStartAddr_p) & ~AligningMask);
TotalSize = ((U32) CurrentStartAddr_p) - ((U32) CurrentAlignedStartAddr_p) + AlignedSize;
/* If the unused memory block is large enough, exit search */
/* if (Cur_p->Size >= TotalSize)*/
if ((Cur_p->Size >= TotalSize) || (Cur_p->Size == 0))
{
#ifdef DEBUG_CODE
if (TotalSize < AllocBlockParams_p->Size)
{
/* Error case */
stavmem_BlockAndBip();
}
#endif
/* Found a unused block matching the requirements ! */
break;
}
}
/* Unsuccessful search: check next block in the partition list */
Cur_p = Cur_p->BlockBelow_p;
}
/* Search is finished: allocate in unused memory block if found */
if (Cur_p != NULL)
{
/* Allocate block structure */
New_p = AllocBlockDescriptor(&(Partition_p->Device_p->TopOfSpaceFreeBlocksList_p));
if (New_p != NULL)
{
/* Block structure allocation successful
Insert new block above current block in partition blocks list */
InsertBlockAboveBlock(&(Partition_p->PartitionVeryTopBlock_p), New_p, Cur_p);
/* Setup new block */
New_p->AllocMode = AllocBlockParams_p->AllocMode; /* STAVMEM_ALLOC_MODE_BOTTOM_TOP */
New_p->StartAddr_p = CurrentAlignedStartAddr_p;
New_p->Size = TotalSize;
New_p->Alignment = Alignment;
New_p->AlignedStartAddr_p = CurrentAlignedStartAddr_p;
New_p->UserSize = AllocBlockParams_p->Size;
New_p->IsUsed = TRUE;
New_p->PartitionHandle = (STAVMEM_PartitionHandle_t) Partition_p;
#ifdef DEBUG_CODE
if ((((U32) New_p->AlignedStartAddr_p) - ((U32) New_p->StartAddr_p) + New_p->UserSize) > New_p->Size)
{
/* ErrorCase */
stavmem_BlockAndBip();
}
#endif
/* Update counter to respect MaxUsedBlocks */
Partition_p->Device_p->CurrentlyUsedBlocks++;
/* Reduce size of unused block and remove it from partition if it is of size 0 */
Cur_p->Size -= TotalSize;
if (Cur_p->Size == 0)
{
/* Remove block from partition list of blocks */
RemoveBlock(&(Partition_p->PartitionVeryTopBlock_p), &(Partition_p->PartitionVeryBottomBlock_p), Cur_p);
/* Free off block structure */
FreeBlockDescriptor(&(Partition_p->Device_p->TopOfSpaceFreeBlocksList_p), Cur_p);
}
}
else
{
/* Failed to allocate new block structure */
Err = STAVMEM_ERROR_MAX_BLOCKS;
}
}
else
{
/* Could not find a large enough memory block matching the allocation requirements */
Err = STAVMEM_ERROR_PARTITION_FULL;
}
}
else /*if (AllocBlockParams_p->AllocMode == STAVMEM_ALLOC_MODE_BOTTOM_TOP)*/
{
/* Search for an unused memory block of size greater than "size" */
Cur_p = Partition_p->PartitionVeryBottomBlock_p;
while (Cur_p != NULL)
{
#ifdef DO_NOT_ALLOW_AREAS_CROSSING
/* Don't allow the "Heap" to overflow the "Stack" */
if (Cur_p->IsUsed && Cur_p->AllocMode != STAVMEM_ALLOC_MODE_BOTTOM_TOP && (Cur_p->AllocMode != STAVMEM_ALLOC_MODE_RESERVED)&& (Cur_p->AllocMode != STAVMEM_ALLOC_MODE_FORBIDDEN))
{
/* Another area is reached: end search unsucessfully */
Cur_p = NULL;
break;
}
#endif
/* Check for a large enough unused block (size 0 means full range so it is enough for sure) */
/* if ((!Cur_p->IsUsed) && (Cur_p->Size >= AlignedSize))*/
if ((!Cur_p->IsUsed) && ((Cur_p->Size >= AlignedSize) || (Cur_p->Size == 0)))
{
/* Block is large enough before alignment, ensure it is still
large enough with alignment constraints */
CurrentAlignedStartAddr_p = (void *) ((((U32) Cur_p->StartAddr_p) + AligningMask) & ~AligningMask);
TotalSize = ((U32) CurrentAlignedStartAddr_p) - ((U32) Cur_p->StartAddr_p) + AlignedSize;
/* If the unused memory block is large enough, exit search */
/* if (Cur_p->Size >= TotalSize)*/
if ((Cur_p->Size >= TotalSize) || (Cur_p->Size == 0))
{
#ifdef DEBUG_CODE
if (TotalSize < AllocBlockParams_p->Size)
{
/* Error case */
stavmem_BlockAndBip();
}
#endif
/* Found a unused block matching the requirements ! */
break;
}
}
/* Unsuccessful search: check next block in the partition list */
Cur_p = Cur_p->BlockAbove_p;
}
/* Search is finished: allocate in unused memory block if found */
if (Cur_p != NULL)
{
/* Allocate block structure */
New_p = AllocBlockDescriptor(&(Partition_p->Device_p->TopOfSpaceFreeBlocksList_p));
if (New_p != NULL)
{
/* Block structure allocation successful
Insert new block below current block in partition blocks list */
InsertBlockBelowBlock(&(Partition_p->PartitionVeryBottomBlock_p), New_p, Cur_p);
/* Setup new block */
New_p->AllocMode = AllocBlockParams_p->AllocMode; /* STAVMEM_ALLOC_MODE_TOP_BOTTOM */
New_p->StartAddr_p = Cur_p->StartAddr_p;
New_p->Size = TotalSize;
New_p->Alignment = Alignment;
New_p->AlignedStartAddr_p = CurrentAlignedStartAddr_p;
New_p->UserSize = AllocBlockParams_p->Size;
New_p->IsUsed = TRUE;
New_p->PartitionHandle = (STAVMEM_PartitionHandle_t) Partition_p;
#ifdef DEBUG_CODE
if ((((U32) New_p->AlignedStartAddr_p) - ((U32) New_p->StartAddr_p) + New_p->UserSize) > New_p->Size)
{
/* ErrorCase */
stavmem_BlockAndBip();
}
#endif
/* Update counter to respect MaxUsedBlocks */
Partition_p->Device_p->CurrentlyUsedBlocks++;
/* Update unused block start address and size, and remove it from partition if it is of size 0 */
Cur_p->StartAddr_p = (void *) (((U32) Cur_p->StartAddr_p) + TotalSize);
Cur_p->Size -= TotalSize;
if (Cur_p->Size == 0)
{
/* Remove block from partition list of blocks */
RemoveBlock(&(Partition_p->PartitionVeryTopBlock_p), &(Partition_p->PartitionVeryBottomBlock_p), Cur_p);
/* Free off block structure */
FreeBlockDescriptor(&(Partition_p->Device_p->TopOfSpaceFreeBlocksList_p), Cur_p);
}
}
else
{
/* Failed to allocate new block structure */
Err = STAVMEM_ERROR_MAX_BLOCKS;
}
}
else
{
/* Could not find a large enough memory block matching the allocation requirements */
Err = STAVMEM_ERROR_PARTITION_FULL;
}
}
/* Unmark forbidden zones now that allocation is done */
UnMarkForbiddenRangesAndBorders(Partition_p);
/* Output block handle as allocation result */
if (New_p == NULL)
{
*BlockHandle_p = STAVMEM_INVALID_BLOCK_HANDLE;
}
else
{
*BlockHandle_p = (STAVMEM_BlockHandle_t) New_p;
}
return(Err);
}
/*
--------------------------------------------------------------------------------
Re-allocate a memory block (with different size)
--------------------------------------------------------------------------------
*/
ST_ErrorCode_t STAVMEM_ReAllocBlock(const STAVMEM_ReAllocBlockParams_t *ReAllocBlockParams_p, STAVMEM_BlockHandle_t *BlockHandle_p)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -