summaryrefslogtreecommitdiffstats
path: root/sys/contrib/ncsw/etc/ncsw_mem.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/ncsw/etc/ncsw_mem.c')
-rw-r--r--sys/contrib/ncsw/etc/ncsw_mem.c763
1 files changed, 763 insertions, 0 deletions
diff --git a/sys/contrib/ncsw/etc/ncsw_mem.c b/sys/contrib/ncsw/etc/ncsw_mem.c
new file mode 100644
index 0000000..f82f0f4
--- /dev/null
+++ b/sys/contrib/ncsw/etc/ncsw_mem.c
@@ -0,0 +1,763 @@
+/******************************************************************************
+
+ © 1995-2003, 2004, 2005-2011 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.
+
+ ALTERNATIVELY, redistribution and use in source and binary forms, with
+ or without modification, are permitted provided that the following
+ conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of Freescale Semiconductor nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+
+ **************************************************************************/
+#include "error_ext.h"
+#include "part_ext.h"
+#include "std_ext.h"
+#include "string_ext.h"
+#include "mem_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), (uintptr_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, uintptr_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 = (uintptr_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-1);
+
+ 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-1);
+
+ /* 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
+ uintptr_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
+ uintptr_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 */
+
+
OpenPOWER on IntegriCloud