summaryrefslogtreecommitdiff
path: root/portable/src/pmemfixed.c
diff options
context:
space:
mode:
Diffstat (limited to 'portable/src/pmemfixed.c')
-rw-r--r--portable/src/pmemfixed.c705
1 files changed, 705 insertions, 0 deletions
diff --git a/portable/src/pmemfixed.c b/portable/src/pmemfixed.c
new file mode 100644
index 0000000..4d16ac1
--- /dev/null
+++ b/portable/src/pmemfixed.c
@@ -0,0 +1,705 @@
+/*---------------------------------------------------------------------------*
+ * pmemfixed.c *
+ * *
+ * Copyright 2007, 2008 Nuance Communciations, Inc. *
+ * *
+ * Licensed under the Apache License, Version 2.0 (the 'License'); *
+ * you may not use this file except in compliance with the License. *
+ * *
+ * You may obtain a copy of the License at *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an 'AS IS' BASIS, *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
+ * See the License for the specific language governing permissions and *
+ * limitations under the License. *
+ * *
+ *---------------------------------------------------------------------------*/
+
+
+
+#include "pmemory.h"
+#include "plog.h"
+
+#undef malloc
+#undef calloc
+#undef realloc
+#undef free
+
+
+#ifdef PORTABLE_FIXED_SIZE_MEM_BLOCK_SCHEME
+
+/*
+ How does the Fixed Size Memory Block Manager Work?
+ The memory manager manages an unlimited number of pools, each containing a linked list
+ of free memory blocks of a fixed size. The memory pools are ordered in increasing block
+ size, eg. pool # 0 contains 4 byte memory blocks, pool # 1 contains 8, etc. Each memory
+ block consists of a header and body. The header (which is currently 8 bytes long) is used
+ to store the address of the next free memory block in the linked list, and to store the
+ memory block's pool ID (this is used by the free function to determine which pool the block
+ originated from). The body is simply the usable memory. Whenever the application requests
+ memory of a given size, the memory manager selects the appropriate memory pool which contain
+ blocks large enough to satisfy the request. The memory manager removes a block from the
+ linked list and returns the address of the memory block body. If there are no blocks
+ available in the pool, then more blocks are created (if there is memory available); the
+ number created is configurable. If it is not possible to create more blocks, then the
+ memory manager searches the remaining pools in the sequence until it finds a free block or
+ it runs out of pools (in this case it will return a null pointer to the calling code).
+
+ How is the memory space allocated to the fixed block pools?
+ At start-up the memory manager requests one large memory block from the system (the size is
+ defined by #define MEM_SIZE). This memory is used to a) create the fixed size memory pools
+ (each contain the initial number defined in the code) and b) to create extra memory blocks
+ each time a particular pool has been exhausted (the number created is configurable for each
+ memory pool also). Once all of this memory has been used up it is also possible to make
+ further requests to the system for more memory (to create more fixed memory blocks); this
+ feature is switched on using the compilation flag ALLOW_ADDITIONAL_SYS_MEM_ALLOCS. Note
+ that once memory blocks have been added to a memory pool they cannot be removed and reused
+ in another, eg a 0.5 MByte memory block could not be removed from its 0.5 Mbyte pool in
+ order to create smaller 4 byte blocks in the 4byte block pool.
+
+ How is the large memory block from the system allocated?
+ It can be allocated in one of three ways depending on compile time definitions. If you define
+ STATIC_MEMORY_POOL, it's allocated as a static array. If you define RTXC_PARTITION_MEMORY,
+ it's allocated from the HEAP_MAP memory partition. If you don't define anything, it's allocated
+ using the system malloc call. Of course, RTXC_PARTITION should only be defined on when you building
+ for the RTXC operating system.
+
+ If STATIC_MEMORY_POOL or RTXC_PARTITION is defined, you cannot define ALLOW_ADDITIONAL_SYS_MEM_ALLOCS.
+
+ Key Points:
+ 1. Configurable memory block sizes (not restricted to power of 2 sizes).
+ 2. Best fit algorith.
+ 3. Dynamically increases the pool sizes (from an initial number).
+ 4. Can limit the total heap size.
+ 5. Configurable initial pool sizes.
+ 6. Allow additional system memory allocations in order to increase the pool sizes when the
+ 'heap' limit has been reached.
+ 7. Doesn't support block consolidation, and reuse across pools.
+
+*/
+
+/*************************** Header Files *************************************/
+
+#ifdef RTXC_PARTITION_MEMORY
+#include <rtxcapi.h>
+/* TODO - When rtxcgen is run, it will create this header file that should contain
+ * identifiers for various memory partitions that we will be using. For now, in order
+ * to get a compile, define a partition identifier.
+ */
+#define HEAP_MAP 1
+
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+
+ /*************************** Macros Definitions *******************************/
+ /* All of these should be defined on the command line
+ * #define MEM_MGR_STATS
+ * #define ALLOW_ADDITIONAL_SYS_MEM_ALLOCS
+ * #define ALLOW_POOL_GROWTHS
+ * #define MEM_SIZE
+ */
+
+ /*
+ #if (defined(STATIC_MEMORY_POOL) || defined(RTXC_PARTITION_MEMORY)) && defined(ALLOW_ADDITIONAL_SYS_MEM_ALLOCS)
+ #error Can't allocate additional memory blocks from the system.
+ #endif
+ */
+ /* TODO: Need to figure out a good size for this. */
+ /* This had better be the same as the block in HEAP_MAP as defined when building RTXC. */
+
+#ifndef MEM_SIZE
+ /* If not defined on the command line, use a default value of 10 megabytes for the heap. */
+#define MEM_SIZE (10 * 1024 * 1024) /* 10 MBytes */
+#endif
+
+#define MEM_BLOCK_HDR 8 /* (bytes): 16 bit Pool ID, 16 bit signature, 32 bit next block pointer */
+#define MEM_POOL_ID_OFFSET 0
+#define NEXT_BLOCK_PTR_OFFSET 1 /* (no. of 4 byte words) */
+#define MEM_BLOCK_HDR_OFFSET 2 /* (no. of 4 byte words) */
+
+#define MEM_POOL_ID_MASK 0x000000FF
+#define MEM_REQ_SIZE_MASK 0xFFFFFF00
+#define MEM_REQ_SIZE_BIT_SHIFT 8
+
+
+
+ /*************************** Type Defs ****************************************/
+
+ typedef struct
+ {
+ unsigned int accReqSize;
+ unsigned int maxReqSize;
+ unsigned int allocated;
+ unsigned int accAllocated;
+ unsigned int accFreed;
+ unsigned int max_alloc;
+ }
+ MEM_STATS;
+
+
+
+ /*************************** Global Variables *********************************/
+
+ int memPoolsInitialised = 0;
+
+ unsigned int memBlockSize[] = { 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288 };
+ /*unsigned int memBlockNum[] = { 400, 1600, 17000, 8192, 13440, 512, 384, 4352, 900, 7000, 256, 2048, 1024, 128, 128, 256, 6000, 2500, 380, 170, 85, 40, 30, 120, 40, 2, 1, 2, 2 };*/
+ unsigned int memBlockNum[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ unsigned int memBlkGrowthNum[] = { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
+
+#define NUM_OF_POOLS (sizeof( memBlockSize ) / sizeof( unsigned int ))
+
+ static unsigned int memBlkGrowths[NUM_OF_POOLS];
+
+#ifdef STATIC_MEMORY_POOL
+ static char pHeap[MEM_SIZE];
+#else
+ static char *pHeap;
+#endif
+ static char* pReservedHeapMem;
+ static char* pMemPools[NUM_OF_POOLS];
+
+ static unsigned int initialHeapSize = MEM_SIZE;
+ static unsigned int usedHeapSize = 0;
+ static unsigned int reservedHeapSize = 0;
+ static unsigned int totalSystemAllocMem = 0;
+ static unsigned int numOfSystemAllocs = 0;
+
+ static MEM_STATS memStats[NUM_OF_POOLS];
+ static unsigned int allocatedMem = 0;
+ static unsigned int maxAllocMem = 0;
+
+
+
+ /*************************** Function Prototypes ******************************/
+
+ void initAllMemPools(void);
+ char* initMemPool(int poolId, int memBlockSize, int numOfMemBlocks, char** startAddress);
+ void* myMalloc(size_t size);
+ void myFree(void* ptr);
+ void displayMemStats(void);
+ void increaseMemPoolSize(unsigned int poolId);
+
+
+
+ /*************************** Function Definitions *****************************/
+
+ /*******************************************************************************
+ *
+ * Function: PortMallocInit
+ *
+ * Args: void
+ *
+ * Returns: void
+ *
+ * Description: API function which initialises the fixed size memory pools. Can
+ * be called multiple times in a session, but is only effective the
+ * first time it is called.
+ *
+ *******************************************************************************/
+
+ void PortMallocInit(void)
+ {
+ if (0 == memPoolsInitialised)
+ {
+ initAllMemPools();
+ }
+ }
+
+
+
+
+
+ int PortMallocGetMaxMemUsed(void)
+ {
+ return (int)maxAllocMem;
+ }
+
+
+
+ /*******************************************************************************
+ *
+ * Function: PortMallocSetPoolSize
+ *
+ * Args: Pool size (size_t)
+ *
+ * Returns: void
+ *
+ * Description: API function used to set the initial heap size. Note this can be
+ * called at any time, but is only effective if the memory manager
+ * has not already been initialised.
+ *
+ *******************************************************************************/
+
+ void PortMallocSetPoolSize(size_t size)
+ {
+#if !defined(STATIC_MEMORY_POOL) && !defined(RTXC_PARTITION_MEMORY)
+ if (!memPoolsInitialised)
+ {
+ initialHeapSize = (unsigned int)size;
+ }
+#else
+ (void)size;
+#endif
+ }
+
+
+
+ /*******************************************************************************
+ *
+ * Function: PortMallocGetPoolSize
+ *
+ * Args: void
+ *
+ * Returns: Pool Size (int)
+ *
+ * Description: API function to return the initial heap size.
+ *
+ *******************************************************************************/
+
+ int PortMallocGetPoolSize(void)
+ {
+ return (int)initialHeapSize;
+ }
+
+
+
+ /*******************************************************************************
+ *
+ * Function: initAllMemPools
+ *
+ * Args: void
+ *
+ * Returns: void
+ *
+ * Description: Internal function which is used to initialise all of the
+ * memory pools. Note it can be called many times but is only
+ * effective the first time it is called.
+ *
+ *******************************************************************************/
+
+ void initAllMemPools(void)
+ {
+ char *availableMemStartAddress;
+
+ if (0 == memPoolsInitialised)
+ {
+ int ii;
+
+ /* Calculate the required heap size */
+ for (ii = 0; ii < NUM_OF_POOLS; ii++)
+ {
+ usedHeapSize += (memBlockSize[ii] + MEM_BLOCK_HDR) * memBlockNum[ii];
+ }
+
+ if (initialHeapSize < usedHeapSize)
+ {
+ /* Insuffucient heap memory; abort initialisation */
+ return;
+ }
+
+
+#if defined(STATIC_MEMORY_POOL)
+ /* pHead has already been allocated, statically. Don't need to do anything. */
+#elif defined(RTXC_PARTITION_MEMORY)
+ /* Grab the one and only block in HEAP_MAP. */
+ pHeap = KS_alloc(HEAP_MAP);
+ /* MEM_SIZE has better equal the size of HEAP_MAP's block. */
+ PORT_ASSERT(MEM_SIZE == KS_inqmap(HEAP_MAP));
+#else
+ /* Use the system malloc for heap allocation. */
+
+ pHeap = (char*)malloc(initialHeapSize);
+#endif
+ if (0 == pHeap)
+ {
+ /* Unable to get memory for heap; abort initialisation */
+ return;
+ }
+
+ totalSystemAllocMem = initialHeapSize;
+ numOfSystemAllocs++;
+ reservedHeapSize = initialHeapSize - usedHeapSize;
+
+ /* Initialise each memory pool */
+ availableMemStartAddress = pHeap;
+
+ for (ii = 0; ii < NUM_OF_POOLS; ii++)
+ {
+ pMemPools[ii] = 0;
+
+ if (0 != memBlockNum[ii])
+ {
+ pMemPools[ii] = initMemPool(ii, memBlockSize[ii] + MEM_BLOCK_HDR, memBlockNum[ii], &availableMemStartAddress);
+ }
+ }
+
+ pReservedHeapMem = availableMemStartAddress;
+
+ memPoolsInitialised = 1;
+ }
+ }
+
+
+
+ /*******************************************************************************
+ *
+ * Function: initMemPool
+ *
+ * Args: Pool ID (int), Memory Block Size (int), Number of Memory Blocks
+ * (int), Heap Memory Start Address (char**)
+ *
+ * Returns: Memory Pool Start Address (char*)
+ *
+ * Description: Internal function used to fill a specified memory pool with a
+ * specified number of memory blocks of a specified size. The heap
+ * memory start address is adjusted to point to the next available
+ * memory following the newly created pool.
+ *
+ *******************************************************************************/
+
+ char* initMemPool(int poolId, int memBlockSize, int numOfMemBlocks, char** startAddress)
+ {
+ char* pPrevMemBlock = 0;
+ char* pCurrMemBlock = 0;
+ char* pStartMemPool = 0;
+ int ii;
+
+ for (ii = 0; ii < numOfMemBlocks; ii++)
+ {
+ pCurrMemBlock = &((*startAddress)[ii*memBlockSize]);
+
+ *((unsigned int*)pCurrMemBlock) = poolId;
+
+ if (0 != pPrevMemBlock)
+ {
+ ((unsigned int*)pPrevMemBlock)[NEXT_BLOCK_PTR_OFFSET] = (unsigned int)pCurrMemBlock;
+ }
+
+ pPrevMemBlock = pCurrMemBlock;
+ }
+
+ ((unsigned int*)pPrevMemBlock)[NEXT_BLOCK_PTR_OFFSET] = 0;
+
+ pStartMemPool = *startAddress;
+
+ *startAddress = (*startAddress) + (ii * memBlockSize);
+
+ return pStartMemPool;
+ }
+
+
+
+ /*******************************************************************************
+ *
+ * Function: PortMalloc
+ *
+ * Args: Size (size_t)
+ *
+ * Returns: Pointer to memory block (void*)
+ *
+ * Description: API function which is used by the application to request memory.
+ * A null pointer is returned if the memory manager is unable to
+ * satisfy the request.
+ *
+ *******************************************************************************/
+
+ void* PortMalloc(size_t size)
+ {
+ int poolId;
+ char *pMemBlock;
+ int ii;
+
+ /* Make sure the memory manager has been initialised */
+ if (0 == memPoolsInitialised)
+ {
+ initAllMemPools();
+ }
+
+ poolId = NUM_OF_POOLS;
+ pMemBlock = 0;
+
+ /* Find the best fit memory block */
+ for (ii = 0; ii < NUM_OF_POOLS; ii++)
+ {
+ if (memBlockSize[ii] >= size)
+ {
+ poolId = ii;
+
+ break;
+ }
+ }
+
+ /* Ensure that the requested size is not larger than the largest block size */
+ if (NUM_OF_POOLS > poolId)
+ {
+ /* Search the selected memory pool for a memory block; if there are none
+ then try to create some more blocks. If this is not possible then
+ search the next largest memory block pool. Repeat until either a block
+ is found, or there are no pools left */
+ for (ii = poolId; ii < NUM_OF_POOLS; ii++)
+ {
+#ifdef ALLOW_POOL_GROWTHS
+ /* If there are no blocks left, try to create some more */
+ if (0 == pMemPools[ii])
+ {
+ increaseMemPoolSize(ii);
+ }
+#endif /* ALLOW_POOL_GROWTHS */
+
+ if (0 != pMemPools[ii])
+ {
+ /* Remove the memory block from the pool linked-list */
+ pMemBlock = pMemPools[ii];
+
+ pMemPools[ii] = (char*)(((unsigned int*)pMemBlock)[NEXT_BLOCK_PTR_OFFSET]);
+
+#ifdef MEM_MGR_STATS
+ /* Record the requested size in the memory block header - this is used
+ by PortFree to determine how much requested memory has been free'd */
+ *((unsigned int*)pMemBlock) = ii | (size << MEM_REQ_SIZE_BIT_SHIFT);
+#endif /* MEM_MGR_STATS */
+
+ /* Adjust the memory block pointer to point to the useful portion of the
+ memory block, ie beyond the header */
+ pMemBlock = pMemBlock + MEM_BLOCK_HDR;
+
+#ifdef MEM_MGR_STATS
+ /* Update the memory statistics */
+ allocatedMem += size;
+
+ if (allocatedMem > maxAllocMem)
+ {
+ maxAllocMem = allocatedMem;
+ }
+
+ memStats[ii].accReqSize += size;
+ memStats[ii].accAllocated++;
+ memStats[ii].allocated++;
+
+ if (memStats[ii].maxReqSize < size)
+ {
+ memStats[ii].maxReqSize = size;
+ }
+
+ if (memStats[ii].allocated > memStats[ii].max_alloc)
+ {
+ memStats[ii].max_alloc = memStats[ii].allocated;
+ }
+#endif /* MEM_MGR_STATS */
+ break;
+ }
+ }
+ }
+
+ return (void*)pMemBlock;
+ }
+
+
+#ifdef ALLOW_POOL_GROWTHS
+ /*******************************************************************************
+ *
+ * Function: increaseMemPoolSize
+ *
+ * Args: Pool ID (unsigned int)
+ *
+ * Returns: void
+ *
+ * Description: Increases the number of blocks in a given pool by the number
+ * specified in the array memBlkGrowthNum if there is memory
+ * available. Memory is allocated from the heap reserve if
+ * availabe, else it is requested from the system (if the
+ * compilation flag ALLOW_ADDITIONAL_SYS_MEM_ALLOCS is defined. If
+ * there is insufficient memory then the operation is aborted
+ * without notification to the calling code.
+ *
+ *******************************************************************************/
+
+ void increaseMemPoolSize(unsigned int poolId)
+ {
+ unsigned int requiredMemSize = memBlkGrowthNum[poolId] * (memBlockSize[poolId] + MEM_BLOCK_HDR);
+
+ /* See if there is enough heap reserve memory */
+ if (requiredMemSize <= reservedHeapSize)
+ {
+ /* We're in luck; there's enough space */
+ pMemPools[poolId] = initMemPool(poolId, memBlockSize[poolId] + MEM_BLOCK_HDR, memBlkGrowthNum[poolId], &pReservedHeapMem);
+
+ memBlockNum[poolId] += memBlkGrowthNum[poolId];
+
+ reservedHeapSize -= requiredMemSize;
+ usedHeapSize += requiredMemSize;
+
+#ifdef MEM_MGR_STATS
+ memBlkGrowths[poolId]++;
+#endif /* MEM_MGR_STATS */
+ }
+#ifdef ALLOW_ADDITIONAL_SYS_MEM_ALLOCS
+ else
+ {
+ /* There's not enough memory in the heap reserve, so request it from the system */
+ char* pStartAddress = (char*)malloc(requiredMemSize);
+
+ if (0 != pStartAddress)
+ {
+ /* The system has allocated some memory, so let's make some more blocks */
+ pMemPools[poolId] = initMemPool(poolId, memBlockSize[poolId] + MEM_BLOCK_HDR, memBlkGrowthNum[poolId], &pStartAddress);
+
+ memBlockNum[poolId] += memBlkGrowthNum[poolId];
+
+ totalSystemAllocMem += requiredMemSize;
+ numOfSystemAllocs++;
+
+#ifdef MEM_MGR_STATS
+ memBlkGrowths[poolId]++;
+#endif /* MEM_MGR_STATS */
+ }
+ }
+#endif /* ALLOW_ADDITIONAL_SYS_MEM_ALLOCS */
+ }
+#endif /* ALLOW_POOL_GROWTHS */
+
+
+
+ /*******************************************************************************
+ *
+ * Function: PortFree
+ *
+ * Args: Memory Block Pointer (void*)
+ *
+ * Returns: void
+ *
+ * Description: API function used by the application code to return a memory
+ * block to the appropriate pool. Note that this function is not
+ * able to handle null or stale memory block pointers; calling this
+ * function under these conditions will result in unpredictable
+ * behavior.
+ *
+ *******************************************************************************/
+
+ void PortFree(void* pMem)
+ {
+ unsigned int tmpVal;
+ unsigned char poolId;
+ char* pCurrentHead;
+#ifdef MEM_MGR_STATS
+ unsigned int reqMemSize;
+#endif
+
+ /* What is the memory block pool id ? */
+ tmpVal = ((unsigned int*)pMem)[-MEM_BLOCK_HDR_OFFSET+MEM_POOL_ID_OFFSET];
+ poolId = tmpVal & MEM_POOL_ID_MASK;
+
+ /* Add the memory block to the appropriate pool */
+ pCurrentHead = pMemPools[poolId];
+ ((unsigned int*)pMem)[-MEM_BLOCK_HDR_OFFSET+NEXT_BLOCK_PTR_OFFSET] = (unsigned int)pCurrentHead;
+ pMemPools[poolId] = (char*) & (((unsigned int*)pMem)[-MEM_BLOCK_HDR_OFFSET]);
+
+#ifdef MEM_MGR_STATS
+ /* What was the requested memory size ? */
+ reqMemSize = tmpVal >> MEM_REQ_SIZE_BIT_SHIFT;
+
+ allocatedMem -= reqMemSize;
+
+ PORT_ASSERT(allocatedMem >= 0);
+
+ memStats[poolId].accFreed++;
+ memStats[poolId].allocated--;
+#endif /* MEM_MGR_STATS */
+ }
+
+
+
+ /*******************************************************************************
+ *
+ * Function: displayMemStats
+ *
+ * Args: void
+ *
+ * Returns: void
+ *
+ * Description: API function used to display the overall memory and individual
+ * memory pool statistics to standard output.
+ *
+ *******************************************************************************/
+
+ void displayMemStats(void)
+ {
+ unsigned int totBNum = 0;
+ unsigned int totGrowths = 0;
+ unsigned int totAlloc = 0;
+ unsigned int totAccAlloc = 0;
+ unsigned int totAccFreed = 0;
+ unsigned int totMaxAlloc = 0;
+ unsigned int totMemWithOH = 0;
+ unsigned int totMem = 0;
+ unsigned int bytesAllocWithOH = 0;
+ unsigned int bytesAlloc = 0;
+ unsigned int maxBytesAllocWithOH = 0;
+ unsigned int maxBytesAlloc = 0;
+ unsigned int ii;
+
+ printf("\nPool ID BlkSz AvReqSz MaxReqSz NumBlk Growths Alloc AccAlloc AccFreed MaxAlloc Alloc(b) MaxA(b)\n");
+ printf("--------------------------------------------------------------------------------------------------------\n");
+
+ for (ii = 0; ii < NUM_OF_POOLS; ii++)
+ {
+ unsigned int avReqSize = 0;
+
+ if (0 != memStats[ii].accAllocated)
+ {
+ avReqSize = memStats[ii].accReqSize / memStats[ii].accAllocated;
+ }
+
+ printf(" %4i %6i %6i %6i %7i %7i %7i %7i %7i %7i %8i %8i\n", ii, memBlockSize[ii], avReqSize, memStats[ii].maxReqSize, memBlockNum[ii], memBlkGrowths[ii], memStats[ii].allocated, memStats[ii].accAllocated, memStats[ii].accFreed, memStats[ii].max_alloc, (memBlockSize[ii]*memStats[ii].allocated), (memBlockSize[ii]*memStats[ii].max_alloc));
+
+ totBNum += memBlockNum[ii];
+ totGrowths += memBlkGrowths[ii];
+ totAlloc += memStats[ii].allocated;
+ totAccAlloc += memStats[ii].accAllocated;
+ totAccFreed += memStats[ii].accFreed;
+ totMaxAlloc += memStats[ii].max_alloc;
+
+ totMemWithOH += (memBlockSize[ii] + MEM_BLOCK_HDR) * memBlockNum[ii];
+ totMem += memBlockSize[ii] * memBlockNum[ii];
+ bytesAllocWithOH += memStats[ii].allocated * (memBlockSize[ii] + MEM_BLOCK_HDR);
+ bytesAlloc += memStats[ii].allocated * memBlockSize[ii];
+ maxBytesAllocWithOH += memStats[ii].max_alloc * (memBlockSize[ii] + MEM_BLOCK_HDR);
+ maxBytesAlloc += memStats[ii].max_alloc * memBlockSize[ii];
+ }
+
+ printf("--------------------------------------------------------------------------------------------------------\n");
+ printf("Total %7i %7i %7i %7i %7i %7i %8i %8i\n\n", totBNum, totGrowths, totAlloc, totAccAlloc, totAccFreed, totMaxAlloc, bytesAlloc, maxBytesAlloc);
+ printf("Total Memory %9i bytes\n", totMemWithOH);
+ printf("Total Memory %9i bytes (without overhead)\n", totMem);
+ printf("Allocated Memory %9i bytes\n", bytesAllocWithOH);
+ printf("Allocated Memory %9i bytes (without overhead)\n", bytesAlloc);
+ printf("Max Alloc Memory %9i bytes\n", maxBytesAllocWithOH);
+ printf("Max Alloc Memory %9i bytes (without overhead)\n", maxBytesAlloc);
+ printf("\nReq Alloc Memory %9i bytes\n", allocatedMem);
+ printf("Max Rq Alloc Mem %9i bytes\n\n", maxAllocMem);
+
+ printf("Used Heap Size %9i bytes\n", usedHeapSize);
+ printf("Reserved Heap %9i bytes\n", reservedHeapSize);
+ printf("Total Sys Alloc %9i bytes\n", totalSystemAllocMem);
+ printf("Num of Sys Alloc %9i\n", numOfSystemAllocs);
+
+ printf("\n");
+ }
+
+
+
+#ifdef __cplusplus
+} /* end extern "C" */
+#endif
+
+
+#endif /* FIXED_SIZE_MEM_BLOCK_SCHEME */