original files of m241
This commit is contained in:
@@ -0,0 +1,739 @@
|
||||
/******************************************************************************
|
||||
|
||||
© 1995-2003, 2004, 2005-2010 Freescale Semiconductor, Inc.
|
||||
All rights reserved.
|
||||
|
||||
This is proprietary source code of Freescale Semiconductor Inc.,
|
||||
and its use is subject to the NetComm Device Drivers EULA.
|
||||
The copyright notice above does not evidence any actual or intended
|
||||
publication of such source code.
|
||||
|
||||
**************************************************************************/
|
||||
#include "error_ext.h"
|
||||
#include "part_ext.h"
|
||||
#include "std_ext.h"
|
||||
#include "string_ext.h"
|
||||
#include "mem_ext.h"
|
||||
#include "hash_ext.h"
|
||||
#include "mem.h"
|
||||
#include "xx_ext.h"
|
||||
|
||||
#define PAD_ALIGNMENT(align, x) (((x)%(align)) ? ((align)-((x)%(align))) : 0)
|
||||
|
||||
#define ALIGN_BLOCK(p_Block, prefixSize, alignment) \
|
||||
do { \
|
||||
p_Block += (prefixSize); \
|
||||
p_Block += PAD_ALIGNMENT((alignment), (uint32_t)(p_Block)); \
|
||||
} while (0)
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#define GET_CALLER_ADDR \
|
||||
__asm__ ("mflr %0" : "=r" (callerAddr))
|
||||
#elif defined(__MWERKS__)
|
||||
/* NOTE: This implementation is only valid for CodeWarrior for PowerPC */
|
||||
#define GET_CALLER_ADDR \
|
||||
__asm__("add %0, 0, %0" : : "r" (callerAddr))
|
||||
#endif /* defined(__GNUC__) */
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
static __inline__ void * MemGet(t_MemorySegment *p_Mem)
|
||||
{
|
||||
uint8_t *p_Block;
|
||||
|
||||
/* check if there is an available block */
|
||||
if (p_Mem->current == p_Mem->num)
|
||||
{
|
||||
p_Mem->getFailures++;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* get the block */
|
||||
p_Block = p_Mem->p_BlocksStack[p_Mem->current];
|
||||
#ifdef DEBUG
|
||||
p_Mem->p_BlocksStack[p_Mem->current] = NULL;
|
||||
#endif /* DEBUG */
|
||||
/* advance current index */
|
||||
p_Mem->current++;
|
||||
|
||||
return (void *)p_Block;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static __inline__ t_Error MemPut(t_MemorySegment *p_Mem, void *p_Block)
|
||||
{
|
||||
/* check if blocks stack is full */
|
||||
if (p_Mem->current > 0)
|
||||
{
|
||||
/* decrease current index */
|
||||
p_Mem->current--;
|
||||
/* put the block */
|
||||
p_Mem->p_BlocksStack[p_Mem->current] = (uint8_t *)p_Block;
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
RETURN_ERROR(MAJOR, E_FULL, NO_MSG);
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG_MEM_LEAKS
|
||||
|
||||
/*****************************************************************************/
|
||||
static t_Error InitMemDebugDatabase(t_MemorySegment *p_Mem)
|
||||
{
|
||||
p_Mem->p_MemDbg = (void *)XX_Malloc(sizeof(t_MemDbg) * p_Mem->num);
|
||||
if (!p_Mem->p_MemDbg)
|
||||
{
|
||||
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory debug object"));
|
||||
}
|
||||
|
||||
memset(p_Mem->p_MemDbg, ILLEGAL_BASE, sizeof(t_MemDbg) * p_Mem->num);
|
||||
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
static t_Error DebugMemGet(t_Handle h_Mem, void *p_Block, uint32_t ownerAddress)
|
||||
{
|
||||
t_MemorySegment *p_Mem = (t_MemorySegment *)h_Mem;
|
||||
t_MemDbg *p_MemDbg = (t_MemDbg *)p_Mem->p_MemDbg;
|
||||
uint32_t blockIndex;
|
||||
|
||||
ASSERT_COND(ownerAddress != ILLEGAL_BASE);
|
||||
|
||||
/* Find block num */
|
||||
if (p_Mem->consecutiveMem)
|
||||
{
|
||||
blockIndex =
|
||||
(((uint8_t *)p_Block - (p_Mem->p_Bases[0] + p_Mem->blockOffset)) / p_Mem->blockSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
blockIndex = *(uint32_t *)((uint8_t *)p_Block - 4);
|
||||
}
|
||||
|
||||
ASSERT_COND(blockIndex < p_Mem->num);
|
||||
ASSERT_COND(p_MemDbg[blockIndex].ownerAddress == ILLEGAL_BASE);
|
||||
|
||||
p_MemDbg[blockIndex].ownerAddress = ownerAddress;
|
||||
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static t_Error DebugMemPut(t_Handle h_Mem, void *p_Block)
|
||||
{
|
||||
t_MemorySegment *p_Mem = (t_MemorySegment *)h_Mem;
|
||||
t_MemDbg *p_MemDbg = (t_MemDbg *)p_Mem->p_MemDbg;
|
||||
uint32_t blockIndex;
|
||||
uint8_t *p_Temp;
|
||||
|
||||
/* Find block num */
|
||||
if (p_Mem->consecutiveMem)
|
||||
{
|
||||
blockIndex =
|
||||
(((uint8_t *)p_Block - (p_Mem->p_Bases[0] + p_Mem->blockOffset)) / p_Mem->blockSize);
|
||||
|
||||
if (blockIndex >= p_Mem->num)
|
||||
{
|
||||
RETURN_ERROR(MAJOR, E_INVALID_ADDRESS,
|
||||
("Freed address (0x%08x) does not belong to this pool", p_Block));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
blockIndex = *(uint32_t *)((uint8_t *)p_Block - 4);
|
||||
|
||||
if (blockIndex >= p_Mem->num)
|
||||
{
|
||||
RETURN_ERROR(MAJOR, E_INVALID_ADDRESS,
|
||||
("Freed address (0x%08x) does not belong to this pool", p_Block));
|
||||
}
|
||||
|
||||
/* Verify that the block matches the corresponding base */
|
||||
p_Temp = p_Mem->p_Bases[blockIndex];
|
||||
|
||||
ALIGN_BLOCK(p_Temp, p_Mem->prefixSize, p_Mem->alignment);
|
||||
|
||||
if (p_Temp == p_Mem->p_Bases[blockIndex])
|
||||
p_Temp += p_Mem->alignment;
|
||||
|
||||
if (p_Temp != p_Block)
|
||||
{
|
||||
RETURN_ERROR(MAJOR, E_INVALID_ADDRESS,
|
||||
("Freed address (0x%08x) does not belong to this pool", p_Block));
|
||||
}
|
||||
}
|
||||
|
||||
if (p_MemDbg[blockIndex].ownerAddress == ILLEGAL_BASE)
|
||||
{
|
||||
RETURN_ERROR(MAJOR, E_ALREADY_FREE,
|
||||
("Attempt to free unallocated address (0x%08x)", p_Block));
|
||||
}
|
||||
|
||||
p_MemDbg[blockIndex].ownerAddress = (uint32_t)ILLEGAL_BASE;
|
||||
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
#endif /* DEBUG_MEM_LEAKS */
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
uint32_t MEM_ComputePartitionSize(uint32_t num,
|
||||
uint16_t dataSize,
|
||||
uint16_t prefixSize,
|
||||
uint16_t postfixSize,
|
||||
uint16_t alignment)
|
||||
{
|
||||
uint32_t blockSize = 0, pad1 = 0, pad2 = 0;
|
||||
|
||||
/* Make sure that the alignment is at least 4 */
|
||||
if (alignment < 4)
|
||||
{
|
||||
alignment = 4;
|
||||
}
|
||||
|
||||
pad1 = (uint32_t)PAD_ALIGNMENT(4, prefixSize);
|
||||
/* Block size not including 2nd padding */
|
||||
blockSize = pad1 + prefixSize + dataSize + postfixSize;
|
||||
pad2 = PAD_ALIGNMENT(alignment, blockSize);
|
||||
/* Block size including 2nd padding */
|
||||
blockSize += pad2;
|
||||
|
||||
return ((num * blockSize) + alignment);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
t_Error MEM_Init(char name[],
|
||||
t_Handle *p_Handle,
|
||||
uint32_t num,
|
||||
uint16_t dataSize,
|
||||
uint16_t prefixSize,
|
||||
uint16_t postfixSize,
|
||||
uint16_t alignment)
|
||||
{
|
||||
uint8_t *p_Memory;
|
||||
uint32_t allocSize;
|
||||
t_Error errCode;
|
||||
|
||||
allocSize = MEM_ComputePartitionSize(num,
|
||||
dataSize,
|
||||
prefixSize,
|
||||
postfixSize,
|
||||
alignment);
|
||||
|
||||
p_Memory = (uint8_t *)XX_Malloc(allocSize);
|
||||
if (!p_Memory)
|
||||
{
|
||||
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment"));
|
||||
}
|
||||
|
||||
errCode = MEM_InitByAddress(name,
|
||||
p_Handle,
|
||||
num,
|
||||
dataSize,
|
||||
prefixSize,
|
||||
postfixSize,
|
||||
alignment,
|
||||
p_Memory);
|
||||
if (errCode != E_OK)
|
||||
{
|
||||
RETURN_ERROR(MAJOR, errCode, NO_MSG);
|
||||
}
|
||||
|
||||
((t_MemorySegment *)(*p_Handle))->allocOwner = e_MEM_ALLOC_OWNER_LOCAL;
|
||||
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
t_Error MEM_InitByAddress(char name[],
|
||||
t_Handle *p_Handle,
|
||||
uint32_t num,
|
||||
uint16_t dataSize,
|
||||
uint16_t prefixSize,
|
||||
uint16_t postfixSize,
|
||||
uint16_t alignment,
|
||||
uint8_t *p_Memory)
|
||||
{
|
||||
t_MemorySegment *p_Mem;
|
||||
uint32_t i, blockSize;
|
||||
uint16_t alignPad, endPad;
|
||||
uint8_t *p_Blocks;
|
||||
|
||||
/* prepare in case of error */
|
||||
*p_Handle = NULL;
|
||||
|
||||
if (!p_Memory)
|
||||
{
|
||||
RETURN_ERROR(MAJOR, E_NULL_POINTER, ("Memory blocks"));
|
||||
}
|
||||
|
||||
p_Blocks = p_Memory;
|
||||
|
||||
/* make sure that the alignment is at least 4 and power of 2 */
|
||||
if (alignment < 4)
|
||||
{
|
||||
alignment = 4;
|
||||
}
|
||||
else if (!POWER_OF_2(alignment))
|
||||
{
|
||||
RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Alignment (should be power of 2)"));
|
||||
}
|
||||
|
||||
/* first allocate the segment descriptor */
|
||||
p_Mem = (t_MemorySegment *)XX_Malloc(sizeof(t_MemorySegment));
|
||||
if (!p_Mem)
|
||||
{
|
||||
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment structure"));
|
||||
}
|
||||
|
||||
/* allocate the blocks stack */
|
||||
p_Mem->p_BlocksStack = (uint8_t **)XX_Malloc(num * sizeof(uint8_t*));
|
||||
if (!p_Mem->p_BlocksStack)
|
||||
{
|
||||
XX_Free(p_Mem);
|
||||
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment block pointers stack"));
|
||||
}
|
||||
|
||||
/* allocate the blocks bases array */
|
||||
p_Mem->p_Bases = (uint8_t **)XX_Malloc(sizeof(uint8_t*));
|
||||
if (!p_Mem->p_Bases)
|
||||
{
|
||||
MEM_Free(p_Mem);
|
||||
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment base pointers array"));
|
||||
}
|
||||
memset(p_Mem->p_Bases, 0, sizeof(uint8_t*));
|
||||
|
||||
/* store info about this segment */
|
||||
p_Mem->num = num;
|
||||
p_Mem->current = 0;
|
||||
p_Mem->dataSize = dataSize;
|
||||
p_Mem->p_Bases[0] = p_Blocks;
|
||||
p_Mem->getFailures = 0;
|
||||
p_Mem->allocOwner = e_MEM_ALLOC_OWNER_EXTERNAL;
|
||||
p_Mem->consecutiveMem = TRUE;
|
||||
p_Mem->prefixSize = prefixSize;
|
||||
p_Mem->postfixSize = postfixSize;
|
||||
p_Mem->alignment = alignment;
|
||||
/* store name */
|
||||
strncpy(p_Mem->name, name, MEM_MAX_NAME_LENGTH);
|
||||
|
||||
p_Mem->h_Spinlock = XX_InitSpinlock();
|
||||
if (!p_Mem->h_Spinlock)
|
||||
{
|
||||
MEM_Free(p_Mem);
|
||||
RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Can't create spinlock!"));
|
||||
}
|
||||
|
||||
alignPad = (uint16_t)PAD_ALIGNMENT(4, prefixSize);
|
||||
/* Make sure the entire size is a multiple of alignment */
|
||||
endPad = (uint16_t)PAD_ALIGNMENT(alignment, (alignPad + prefixSize + dataSize + postfixSize));
|
||||
|
||||
/* The following manipulation places the data of block[0] in an aligned address,
|
||||
since block size is aligned the following block datas will all be aligned */
|
||||
ALIGN_BLOCK(p_Blocks, prefixSize, alignment);
|
||||
|
||||
blockSize = (uint32_t)(alignPad + prefixSize + dataSize + postfixSize + endPad);
|
||||
|
||||
/* initialize the blocks */
|
||||
for (i=0; i < num; i++)
|
||||
{
|
||||
p_Mem->p_BlocksStack[i] = p_Blocks;
|
||||
p_Blocks += blockSize;
|
||||
}
|
||||
|
||||
/* return handle to caller */
|
||||
*p_Handle = (t_Handle)p_Mem;
|
||||
|
||||
#ifdef DEBUG_MEM_LEAKS
|
||||
{
|
||||
t_Error errCode = InitMemDebugDatabase(p_Mem);
|
||||
|
||||
if (errCode != E_OK)
|
||||
RETURN_ERROR(MAJOR, errCode, NO_MSG);
|
||||
|
||||
p_Mem->blockOffset = (uint32_t)(p_Mem->p_BlocksStack[0] - p_Mem->p_Bases[0]);
|
||||
p_Mem->blockSize = blockSize;
|
||||
}
|
||||
#endif /* DEBUG_MEM_LEAKS */
|
||||
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
t_Error MEM_InitSmart(char name[],
|
||||
t_Handle *p_Handle,
|
||||
uint32_t num,
|
||||
uint16_t dataSize,
|
||||
uint16_t prefixSize,
|
||||
uint16_t postfixSize,
|
||||
uint16_t alignment,
|
||||
uint8_t memPartitionId,
|
||||
bool consecutiveMem)
|
||||
{
|
||||
t_MemorySegment *p_Mem;
|
||||
uint32_t i, blockSize;
|
||||
uint16_t alignPad, endPad;
|
||||
|
||||
/* prepare in case of error */
|
||||
*p_Handle = NULL;
|
||||
|
||||
/* make sure that size is always a multiple of 4 */
|
||||
if (dataSize & 3)
|
||||
{
|
||||
dataSize &= ~3;
|
||||
dataSize += 4;
|
||||
}
|
||||
|
||||
/* make sure that the alignment is at least 4 and power of 2 */
|
||||
if (alignment < 4)
|
||||
{
|
||||
alignment = 4;
|
||||
}
|
||||
else if (!POWER_OF_2(alignment))
|
||||
{
|
||||
RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Alignment (should be power of 2)"));
|
||||
}
|
||||
|
||||
/* first allocate the segment descriptor */
|
||||
p_Mem = (t_MemorySegment *)XX_Malloc(sizeof(t_MemorySegment));
|
||||
if (!p_Mem)
|
||||
{
|
||||
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment structure"));
|
||||
}
|
||||
|
||||
/* allocate the blocks stack */
|
||||
p_Mem->p_BlocksStack = (uint8_t **)XX_Malloc(num * sizeof(uint8_t*));
|
||||
if (!p_Mem->p_BlocksStack)
|
||||
{
|
||||
MEM_Free(p_Mem);
|
||||
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment block pointers stack"));
|
||||
}
|
||||
|
||||
/* allocate the blocks bases array */
|
||||
p_Mem->p_Bases = (uint8_t **)XX_Malloc((consecutiveMem ? 1 : num) * sizeof(uint8_t*));
|
||||
if (!p_Mem->p_Bases)
|
||||
{
|
||||
MEM_Free(p_Mem);
|
||||
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment base pointers array"));
|
||||
}
|
||||
memset(p_Mem->p_Bases, 0, (consecutiveMem ? 1 : num) * sizeof(uint8_t*));
|
||||
|
||||
/* store info about this segment */
|
||||
p_Mem->num = num;
|
||||
p_Mem->current = 0;
|
||||
p_Mem->dataSize = dataSize;
|
||||
p_Mem->getFailures = 0;
|
||||
p_Mem->allocOwner = e_MEM_ALLOC_OWNER_LOCAL_SMART;
|
||||
p_Mem->consecutiveMem = consecutiveMem;
|
||||
p_Mem->prefixSize = prefixSize;
|
||||
p_Mem->postfixSize = postfixSize;
|
||||
p_Mem->alignment = alignment;
|
||||
|
||||
p_Mem->h_Spinlock = XX_InitSpinlock();
|
||||
if (!p_Mem->h_Spinlock)
|
||||
{
|
||||
MEM_Free(p_Mem);
|
||||
RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Can't create spinlock!"));
|
||||
}
|
||||
|
||||
alignPad = (uint16_t)PAD_ALIGNMENT(4, prefixSize);
|
||||
/* Make sure the entire size is a multiple of alignment */
|
||||
endPad = (uint16_t)PAD_ALIGNMENT(alignment, alignPad + prefixSize + dataSize + postfixSize);
|
||||
|
||||
/* Calculate blockSize */
|
||||
blockSize = (uint32_t)(alignPad + prefixSize + dataSize + postfixSize + endPad);
|
||||
|
||||
/* Now allocate the blocks */
|
||||
if (p_Mem->consecutiveMem)
|
||||
{
|
||||
/* |alignment - 1| bytes at most will be discarded in the beginning of the
|
||||
received segment for alignment reasons, therefore the allocation is of:
|
||||
(alignment + (num * block size)). */
|
||||
uint8_t *p_Blocks = (uint8_t *)
|
||||
XX_MallocSmart((uint32_t)((num * blockSize) + alignment), memPartitionId, 1);
|
||||
if (!p_Blocks)
|
||||
{
|
||||
MEM_Free(p_Mem);
|
||||
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment blocks"));
|
||||
}
|
||||
|
||||
/* Store the memory segment address */
|
||||
p_Mem->p_Bases[0] = p_Blocks;
|
||||
|
||||
/* The following manipulation places the data of block[0] in an aligned address,
|
||||
since block size is aligned the following block datas will all be aligned.*/
|
||||
ALIGN_BLOCK(p_Blocks, prefixSize, alignment);
|
||||
|
||||
/* initialize the blocks */
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
p_Mem->p_BlocksStack[i] = p_Blocks;
|
||||
p_Blocks += blockSize;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_MEM_LEAKS
|
||||
p_Mem->blockOffset = (uint32_t)(p_Mem->p_BlocksStack[0] - p_Mem->p_Bases[0]);
|
||||
p_Mem->blockSize = blockSize;
|
||||
#endif /* DEBUG_MEM_LEAKS */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* |alignment - 1| bytes at most will be discarded in the beginning of the
|
||||
received segment for alignment reasons, therefore the allocation is of:
|
||||
(alignment + block size). */
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
uint8_t *p_Block = (uint8_t *)
|
||||
XX_MallocSmart((uint32_t)(blockSize + alignment), memPartitionId, 1);
|
||||
if (!p_Block)
|
||||
{
|
||||
MEM_Free(p_Mem);
|
||||
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment blocks"));
|
||||
}
|
||||
|
||||
/* Store the memory segment address */
|
||||
p_Mem->p_Bases[i] = p_Block;
|
||||
|
||||
/* The following places the data of each block in an aligned address */
|
||||
ALIGN_BLOCK(p_Block, prefixSize, alignment);
|
||||
|
||||
#ifdef DEBUG_MEM_LEAKS
|
||||
/* Need 4 bytes before the meaningful bytes to store the block index.
|
||||
We know we have them because alignment is at least 4 bytes. */
|
||||
if (p_Block == p_Mem->p_Bases[i])
|
||||
p_Block += alignment;
|
||||
|
||||
*(uint32_t *)(p_Block - 4) = i;
|
||||
#endif /* DEBUG_MEM_LEAKS */
|
||||
|
||||
p_Mem->p_BlocksStack[i] = p_Block;
|
||||
}
|
||||
}
|
||||
|
||||
/* store name */
|
||||
strncpy(p_Mem->name, name, MEM_MAX_NAME_LENGTH);
|
||||
|
||||
/* return handle to caller */
|
||||
*p_Handle = (t_Handle)p_Mem;
|
||||
|
||||
#ifdef DEBUG_MEM_LEAKS
|
||||
{
|
||||
t_Error errCode = InitMemDebugDatabase(p_Mem);
|
||||
|
||||
if (errCode != E_OK)
|
||||
RETURN_ERROR(MAJOR, errCode, NO_MSG);
|
||||
}
|
||||
#endif /* DEBUG_MEM_LEAKS */
|
||||
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
void MEM_Free(t_Handle h_Mem)
|
||||
{
|
||||
t_MemorySegment *p_Mem = (t_MemorySegment*)h_Mem;
|
||||
uint32_t num, i;
|
||||
|
||||
/* Check MEM leaks */
|
||||
MEM_CheckLeaks(h_Mem);
|
||||
|
||||
if (p_Mem)
|
||||
{
|
||||
num = p_Mem->consecutiveMem ? 1 : p_Mem->num;
|
||||
|
||||
if (p_Mem->allocOwner == e_MEM_ALLOC_OWNER_LOCAL_SMART)
|
||||
{
|
||||
for (i=0; i < num; i++)
|
||||
{
|
||||
if (p_Mem->p_Bases[i])
|
||||
{
|
||||
XX_FreeSmart(p_Mem->p_Bases[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (p_Mem->allocOwner == e_MEM_ALLOC_OWNER_LOCAL)
|
||||
{
|
||||
for (i=0; i < num; i++)
|
||||
{
|
||||
if (p_Mem->p_Bases[i])
|
||||
{
|
||||
XX_Free(p_Mem->p_Bases[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p_Mem->h_Spinlock)
|
||||
XX_FreeSpinlock(p_Mem->h_Spinlock);
|
||||
|
||||
if (p_Mem->p_Bases)
|
||||
XX_Free(p_Mem->p_Bases);
|
||||
|
||||
if (p_Mem->p_BlocksStack)
|
||||
XX_Free(p_Mem->p_BlocksStack);
|
||||
|
||||
#ifdef DEBUG_MEM_LEAKS
|
||||
if (p_Mem->p_MemDbg)
|
||||
XX_Free(p_Mem->p_MemDbg);
|
||||
#endif /* DEBUG_MEM_LEAKS */
|
||||
|
||||
XX_Free(p_Mem);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
void * MEM_Get(t_Handle h_Mem)
|
||||
{
|
||||
t_MemorySegment *p_Mem = (t_MemorySegment *)h_Mem;
|
||||
uint8_t *p_Block;
|
||||
uint32_t intFlags;
|
||||
#ifdef DEBUG_MEM_LEAKS
|
||||
uint32_t callerAddr = 0;
|
||||
|
||||
GET_CALLER_ADDR;
|
||||
#endif /* DEBUG_MEM_LEAKS */
|
||||
|
||||
ASSERT_COND(h_Mem);
|
||||
|
||||
intFlags = XX_LockIntrSpinlock(p_Mem->h_Spinlock);
|
||||
/* check if there is an available block */
|
||||
if ((p_Block = (uint8_t *)MemGet(p_Mem)) == NULL)
|
||||
{
|
||||
XX_UnlockIntrSpinlock(p_Mem->h_Spinlock, intFlags);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_MEM_LEAKS
|
||||
DebugMemGet(p_Mem, p_Block, callerAddr);
|
||||
#endif /* DEBUG_MEM_LEAKS */
|
||||
XX_UnlockIntrSpinlock(p_Mem->h_Spinlock, intFlags);
|
||||
|
||||
return (void *)p_Block;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
uint16_t MEM_GetN(t_Handle h_Mem, uint32_t num, void *array[])
|
||||
{
|
||||
t_MemorySegment *p_Mem = (t_MemorySegment *)h_Mem;
|
||||
uint32_t availableBlocks;
|
||||
register uint32_t i;
|
||||
uint32_t intFlags;
|
||||
#ifdef DEBUG_MEM_LEAKS
|
||||
uint32_t callerAddr = 0;
|
||||
|
||||
GET_CALLER_ADDR;
|
||||
#endif /* DEBUG_MEM_LEAKS */
|
||||
|
||||
ASSERT_COND(h_Mem);
|
||||
|
||||
intFlags = XX_LockIntrSpinlock(p_Mem->h_Spinlock);
|
||||
/* check how many blocks are available */
|
||||
availableBlocks = (uint32_t)(p_Mem->num - p_Mem->current);
|
||||
if (num > availableBlocks)
|
||||
{
|
||||
num = availableBlocks;
|
||||
}
|
||||
|
||||
for (i=0; i < num; i++)
|
||||
{
|
||||
/* get pointer to block */
|
||||
if ((array[i] = MemGet(p_Mem)) == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_MEM_LEAKS
|
||||
DebugMemGet(p_Mem, array[i], callerAddr);
|
||||
#endif /* DEBUG_MEM_LEAKS */
|
||||
}
|
||||
XX_UnlockIntrSpinlock(p_Mem->h_Spinlock, intFlags);
|
||||
|
||||
return (uint16_t)i;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
t_Error MEM_Put(t_Handle h_Mem, void *p_Block)
|
||||
{
|
||||
t_MemorySegment *p_Mem = (t_MemorySegment *)h_Mem;
|
||||
t_Error rc;
|
||||
uint32_t intFlags;
|
||||
|
||||
ASSERT_COND(h_Mem);
|
||||
|
||||
intFlags = XX_LockIntrSpinlock(p_Mem->h_Spinlock);
|
||||
/* check if blocks stack is full */
|
||||
if ((rc = MemPut(p_Mem, p_Block)) != E_OK)
|
||||
{
|
||||
XX_UnlockIntrSpinlock(p_Mem->h_Spinlock, intFlags);
|
||||
RETURN_ERROR(MAJOR, rc, NO_MSG);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_MEM_LEAKS
|
||||
DebugMemPut(p_Mem, p_Block);
|
||||
#endif /* DEBUG_MEM_LEAKS */
|
||||
XX_UnlockIntrSpinlock(p_Mem->h_Spinlock, intFlags);
|
||||
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG_MEM_LEAKS
|
||||
|
||||
/*****************************************************************************/
|
||||
void MEM_CheckLeaks(t_Handle h_Mem)
|
||||
{
|
||||
t_MemorySegment *p_Mem = (t_MemorySegment *)h_Mem;
|
||||
t_MemDbg *p_MemDbg = (t_MemDbg *)p_Mem->p_MemDbg;
|
||||
uint8_t *p_Block;
|
||||
int i;
|
||||
|
||||
ASSERT_COND(h_Mem);
|
||||
|
||||
if (p_Mem->consecutiveMem)
|
||||
{
|
||||
for (i=0; i < p_Mem->num; i++)
|
||||
{
|
||||
if (p_MemDbg[i].ownerAddress != ILLEGAL_BASE)
|
||||
{
|
||||
/* Find the block address */
|
||||
p_Block = ((p_Mem->p_Bases[0] + p_Mem->blockOffset) +
|
||||
(i * p_Mem->blockSize));
|
||||
|
||||
XX_Print("MEM leak: 0x%08x, Caller address: 0x%08x\n",
|
||||
p_Block, p_MemDbg[i].ownerAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=0; i < p_Mem->num; i++)
|
||||
{
|
||||
if (p_MemDbg[i].ownerAddress != ILLEGAL_BASE)
|
||||
{
|
||||
/* Find the block address */
|
||||
p_Block = p_Mem->p_Bases[i];
|
||||
|
||||
ALIGN_BLOCK(p_Block, p_Mem->prefixSize, p_Mem->alignment);
|
||||
|
||||
if (p_Block == p_Mem->p_Bases[i])
|
||||
p_Block += p_Mem->alignment;
|
||||
|
||||
XX_Print("MEM leak: 0x%08x, Caller address: 0x%08x\n",
|
||||
p_Block, p_MemDbg[i].ownerAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* DEBUG_MEM_LEAKS */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user