summaryrefslogtreecommitdiff
path: root/portable/src/pmemblock.c
diff options
context:
space:
mode:
Diffstat (limited to 'portable/src/pmemblock.c')
-rw-r--r--portable/src/pmemblock.c544
1 files changed, 544 insertions, 0 deletions
diff --git a/portable/src/pmemblock.c b/portable/src/pmemblock.c
new file mode 100644
index 0000000..5f3277d
--- /dev/null
+++ b/portable/src/pmemblock.c
@@ -0,0 +1,544 @@
+/*---------------------------------------------------------------------------*
+ * pmemblock.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 "ptypes.h"
+
+#if PORTABLE_MEM_MGR == PORTABLE_PSOS_BLOCK_SCHEME_MEM_MGR
+
+#ifdef PSOSIM
+#define PSOS
+#endif
+
+#ifdef PSOS
+#include <stdlib.h>
+#include <psos.h>
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /* Data *****************************************************************/
+
+#define NUM_POOL_BINS 32
+#define NUM_POOL_SLOTS 8
+
+ typedef struct memory_pools
+ {
+ uint32 currentNumberOfPools;
+
+ struct pool_info
+ {
+ unsigned long poolId;
+ void* pMemory;
+ unsigned long size;
+ }
+ poolInfo[NUM_POOL_SLOTS];
+
+ }
+ MEMORY_POOL;
+
+ static MEMORY_POOL memoryPool[NUM_POOL_BINS];
+
+#define NUM_TRACKING_BINS NUM_POOL_BINS
+
+ /* Object tracking variables */
+ static struct tracking_struct
+ {
+ uint32 sCurrentAllocationSize;
+ uint32 sMaximumAllocationSize;
+ uint32 sTotalAllocationSize;
+
+ uint32 sCurrentAllocRealSize;
+ uint32 sMaximumAllocRealSize;
+ uint32 sTotalAllocRealSize;
+
+ uint32 sCurrentAllocationNumber;
+ uint32 sMaximumAllocationNumber;
+ uint32 sTotalAllocationNumber;
+
+ uint32 sCurrentAllocationNumberArray[NUM_TRACKING_BINS];
+ uint32 sMaximumAllocationNumberArray[NUM_TRACKING_BINS];
+ uint32 sTotalAllocationNumberArray[NUM_TRACKING_BINS];
+
+ uint32 sCurrentAllocationSizeArray[NUM_TRACKING_BINS];
+ uint32 sMaximumAllocationSizeArray[NUM_TRACKING_BINS];
+ uint32 sTotalAllocationSizeArray[NUM_TRACKING_BINS];
+ }
+ gMemoryTracking;
+
+
+ /* Functions *********************************************************/
+
+ static uint32 findBin(size_t size)
+ {
+ int i, bin;
+ for (i = 0, bin = 1; i < NUM_TRACKING_BINS; i++, bin <<= 1)
+ {
+ if ((int)size <= bin)
+ return i;
+ }
+
+ return 0;
+ }
+
+
+ static void MemoryTrackingInit(void)
+ {
+ int i;
+ /* Initialization of object tracking variables */
+ gMemoryTracking.sCurrentAllocationSize = 0;
+ gMemoryTracking.sMaximumAllocationSize = 0;
+ gMemoryTracking.sTotalAllocationSize = 0;
+
+ gMemoryTracking.sCurrentAllocationNumber = 0;
+ gMemoryTracking.sMaximumAllocationNumber = 0;
+ gMemoryTracking.sTotalAllocationNumber = 0;
+
+ gMemoryTracking.sCurrentAllocRealSize = 0;
+ gMemoryTracking.sMaximumAllocRealSize = 0;
+ gMemoryTracking.sTotalAllocRealSize = 0;
+
+ for (i = 0; i < NUM_TRACKING_BINS; i++)
+ {
+ gMemoryTracking.sCurrentAllocationNumberArray[i] = 0;
+ gMemoryTracking.sMaximumAllocationNumberArray[i] = 0;
+ gMemoryTracking.sTotalAllocationNumberArray[i] = 0;
+
+ gMemoryTracking.sCurrentAllocationSizeArray[i] = 0;
+ gMemoryTracking.sMaximumAllocationSizeArray[i] = 0;
+ gMemoryTracking.sTotalAllocationSizeArray[i] = 0;
+ }
+ }
+
+
+ static void MemoryTrackingAdd(size_t size)
+ {
+ /* Memory tracking code */
+ uint32 bin = findBin(size);
+ uint32 binsize = 1 << bin;
+ uint32 dummy;
+
+ /* for breakpoint setting */
+#ifdef PSOSIM
+ if (bin == 0)
+ dummy = 0;
+ if (bin == 1)
+ dummy = 0;
+ if (bin == 2)
+ dummy = 0;
+ if (bin == 3)
+ dummy = 0;
+ if (bin == 4)
+ dummy = 0;
+ if (bin == 5)
+ dummy = 0;
+ if (bin == 6)
+ dummy = 0;
+ if (bin == 7)
+ dummy = 0;
+ if (bin == 8)
+ dummy = 0;
+ if (bin == 9)
+ dummy = 0;
+ if (bin == 10)
+ dummy = 0;
+ if (bin == 11)
+ dummy = 0;
+ if (bin == 12)
+ dummy = 0;
+ if (bin == 13)
+ dummy = 0;
+ if (bin == 14)
+ dummy = 0;
+ if (bin == 15)
+ dummy = 0;
+ if (bin == 16)
+ dummy = 0;
+ if (bin == 17)
+ dummy = 0;
+ if (bin == 18)
+ dummy = 0;
+ if (bin == 19)
+ dummy = 0;
+ if (bin == 20)
+ dummy = 0;
+ if (bin == 21)
+ dummy = 0;
+ if (bin > 21)
+ dummy = 0;
+#endif /* PSOSIM */
+
+ gMemoryTracking.sCurrentAllocationSize += size;
+ gMemoryTracking.sTotalAllocationSize += size;
+ if (gMemoryTracking.sCurrentAllocationSize > gMemoryTracking.sMaximumAllocationSize)
+ gMemoryTracking.sMaximumAllocationSize = gMemoryTracking.sCurrentAllocationSize;
+
+ gMemoryTracking.sCurrentAllocRealSize += binsize;
+ gMemoryTracking.sTotalAllocRealSize += binsize;
+ if (gMemoryTracking.sCurrentAllocRealSize > gMemoryTracking.sMaximumAllocRealSize)
+ gMemoryTracking.sMaximumAllocRealSize = gMemoryTracking.sCurrentAllocRealSize;
+
+ gMemoryTracking.sCurrentAllocationNumber++;
+ gMemoryTracking.sTotalAllocationNumber++;
+ if (gMemoryTracking.sCurrentAllocationNumber > gMemoryTracking.sMaximumAllocationNumber)
+ gMemoryTracking.sMaximumAllocationNumber = gMemoryTracking.sCurrentAllocationNumber;
+
+ gMemoryTracking.sCurrentAllocationSizeArray[bin] += size;
+ gMemoryTracking.sTotalAllocationSizeArray[bin] += size;
+ if (gMemoryTracking.sCurrentAllocationSizeArray[bin] > gMemoryTracking.sMaximumAllocationSizeArray[bin])
+ gMemoryTracking.sMaximumAllocationSizeArray[bin] = gMemoryTracking.sCurrentAllocationSizeArray[bin];
+
+ gMemoryTracking.sCurrentAllocationNumberArray[bin]++;
+ gMemoryTracking.sTotalAllocationNumberArray[bin]++;
+ if (gMemoryTracking.sCurrentAllocationNumberArray[bin] > gMemoryTracking.sMaximumAllocationNumberArray[bin])
+ gMemoryTracking.sMaximumAllocationNumberArray[bin] = gMemoryTracking.sCurrentAllocationNumberArray[bin];
+ }
+
+
+ static void MemoryTrackingDelete(unsigned long size)
+ {
+ /* Memory tracking code */
+ uint32 bin = findBin(size);
+ uint32 binsize = 1 << bin;
+
+ gMemoryTracking.sCurrentAllocationSize -= size;
+ gMemoryTracking.sCurrentAllocationNumber--;
+
+ gMemoryTracking.sCurrentAllocationSizeArray[bin] -= size;
+ gMemoryTracking.sCurrentAllocationNumberArray[bin]--;
+
+ gMemoryTracking.sCurrentAllocRealSize -= binsize;
+ }
+
+
+ static void InitPools(void)
+ {
+ int i, j;
+ for (i = 0; i < NUM_POOL_BINS; i++)
+ {
+ memoryPool[i].currentNumberOfPools = 0;
+
+ for (j = 0; j < NUM_POOL_SLOTS; j++)
+ {
+ memoryPool[i].poolInfo[j].poolId = 0;
+ memoryPool[i].poolInfo[j].pMemory = NULL;
+ memoryPool[i].poolInfo[j].size = 0;
+ }
+ }
+ }
+
+
+ static void TermPools(void)
+ {
+ int i, j;
+ /* For some reason, deleting the region then freeing the memory causes a failure */
+ /* TODO: Figure out why??? */
+ for (i = 1; i < NUM_POOL_BINS; i++)
+ {
+ for (j = 0; j < (int)memoryPool[i].currentNumberOfPools; j++)
+ {
+ if (memoryPool[i].poolInfo[j].pMemory != NULL)
+ {
+ unsigned long retval = pt_delete(memoryPool[i].poolInfo[j].poolId);
+ PORT_ASSERT(retval == 0);
+
+ PORT_ASSERT_GOOD_WRITE_POINTER(memoryPool[i].poolInfo[j].pMemory);
+ free(memoryPool[i].poolInfo[j].pMemory);
+
+ memoryPool[i].poolInfo[j].poolId = 0;
+ memoryPool[i].poolInfo[j].pMemory = NULL;
+ memoryPool[i].poolInfo[j].size = 0;
+ }
+ }
+
+ memoryPool[i].currentNumberOfPools = 0;
+ }
+ }
+
+
+#define PARTITION_CONTROL_BLOCK_SIZE 0x400
+
+ static BOOL CreatePool(uint32 whichPool, uint32 poolSize)
+ {
+ static uint32 poolNumber = 0;
+
+ void* pMemory = NULL;
+ unsigned long poolId, unused;
+
+ uint32 currentNumberOfPools = memoryPool[whichPool].currentNumberOfPools;
+
+ PORT_ASSERT((whichPool >= 0) && (whichPool < NUM_POOL_BINS));
+
+ if (currentNumberOfPools == NUM_POOL_SLOTS)
+ return FALSE;
+
+
+ if (whichPool < 2)
+ {
+ /* Invalid partition size */
+ return FALSE;
+ }
+ else
+ {
+ char name[5];
+ unsigned long retval;
+
+ pMemory = malloc(poolSize * (1 << whichPool) + PARTITION_CONTROL_BLOCK_SIZE);
+ PORT_ASSERT_GOOD_WRITE_POINTER(pMemory);
+
+ /* No memory protection */
+ if (pMemory == NULL)
+ {
+ /* No memory left in system */
+ return FALSE;
+ }
+
+
+ sprintf(name, "DP%02d", poolNumber);
+
+ retval = pt_create(name, pMemory, 0, poolSize * (1 << whichPool) + PARTITION_CONTROL_BLOCK_SIZE,
+ 1 << whichPool, PT_LOCAL | PT_DEL, &poolId, &unused);
+ if (retval != 0)
+ {
+ /* Unable to create a pSOS partition */
+ return FALSE;
+ }
+ }
+
+ memoryPool[whichPool].poolInfo[currentNumberOfPools].poolId = poolId;
+ memoryPool[whichPool].poolInfo[currentNumberOfPools].pMemory = pMemory;
+ memoryPool[whichPool].poolInfo[currentNumberOfPools].size = poolSize;
+ memoryPool[whichPool].currentNumberOfPools++;
+
+ poolNumber++;
+
+ return TRUE;
+ }
+
+ static BOOL AddPool(uint32 whichPool, uint32 poolSize)
+ {
+ if (memoryPool[whichPool].poolInfo[0].pMemory == NULL)
+ return FALSE;
+
+ return CreatePool(whichPool, poolSize);
+ }
+
+ static void* AllocateFromPsos(uint32 whichPool, uint32 poolIndex, uint32 size)
+ {
+ uint32 retval;
+ void* pMemory;
+
+ PORT_ASSERT(memoryPool[whichPool].poolInfo[poolIndex].poolId);
+
+ retval = pt_getbuf(memoryPool[whichPool].poolInfo[poolIndex].poolId, &pMemory);
+
+ /* If we got memory, then return */
+ if (retval == 0)
+ {
+ PORT_ASSERT_GOOD_WRITE_POINTER(pMemory);
+ *((unsigned long *)pMemory) = (whichPool << 27) + (poolIndex << 24) + size;
+ return (unsigned long *)pMemory + 1;
+ }
+ else
+ return NULL;
+ }
+
+ static void* SearchPoolsForMemory(uint32 whichPool, uint32 size)
+ {
+ void* pMemory;
+ uint32 poolIndex;
+ /* Get memory from main region */
+ if (whichPool == 0)
+ {
+ pMemory = malloc(size);
+
+ /* No memory protection */
+ if (pMemory == NULL)
+ {
+ /* No memory left in system */
+ return NULL;
+ }
+
+ PORT_ASSERT_GOOD_WRITE_POINTER(pMemory);
+ *((unsigned long *)pMemory) = (whichPool << 27) + size;
+ return (unsigned long *)pMemory + 1;
+ }
+
+ /* Allocate memory from the first available bin (partition) */
+ for (poolIndex = 0; poolIndex < memoryPool[whichPool].currentNumberOfPools; poolIndex++)
+ {
+ pMemory = AllocateFromPsos(whichPool, poolIndex, size);
+ if (pMemory != NULL)
+ return pMemory;
+ }
+
+ /* Made it here because we ran out of memory in the pool, so try to add more pools */
+ if (AddPool(whichPool, memoryPool[whichPool].poolInfo[0].size >> 1) == FALSE)
+ {
+ /* All pools of this size have been consumed */
+ return NULL;
+ }
+
+ /* Allocate memory from newly created pool */
+ pMemory = AllocateFromPsos(whichPool, memoryPool[whichPool].currentNumberOfPools - 1, size);
+ if (pMemory != NULL)
+ return pMemory;
+
+ /* If we can't allocate from the newly created pool, then we have problems */
+ /* No memory protection */
+
+ /* No memory left in system */
+ return NULL;
+ }
+
+ void* PortMemBlockAllocateFromPool(uint32 size)
+ {
+ void* pMemory = NULL;
+ int poolIndex;
+ BOOL foundPool = FALSE;
+ uint32 whichPool;
+
+ PORT_ASSERT((size & 0xff000000) == 0);
+
+ size += 4;
+ whichPool = findBin(size); /* Add 4 so I can store info with data */
+ MemoryTrackingAdd(size);
+
+ /* If pool exists for the size needed, then use it, else find next largest pool */
+ for (poolIndex = whichPool; poolIndex < 32; poolIndex++)
+ if (memoryPool[poolIndex].poolInfo[0].pMemory != NULL)
+ {
+ foundPool = TRUE;
+ whichPool = poolIndex;
+ break;
+ }
+
+ /* If next largest pool doesn't exist, then use pool 0 (regions) */
+ if (!foundPool)
+ whichPool = 0;
+
+ /* Allocate memory from the first available bin */
+ pMemory = SearchPoolsForMemory(whichPool, size);
+ PORT_ASSERT_GOOD_WRITE_POINTER(pMemory);
+ return pMemory;
+ }
+
+ void PortMemBlockDeleteFromPool(void* pMemory)
+ {
+ unsigned long *pRealMemory = (unsigned long *)pMemory - 1;
+
+ uint32 whichPool = (*pRealMemory >> 27) & 0x0000001f;
+ uint32 whichBin = (*pRealMemory >> 24) & 0x00000007;
+
+ PORT_ASSERT_GOOD_WRITE_POINTER(pMemory);
+ MemoryTrackingDelete(*pRealMemory & 0x00ffffff);
+
+
+ if (whichPool == 0)
+ {
+ free(pRealMemory);
+ }
+ else
+ {
+ uint32 retval = pt_retbuf(memoryPool[whichPool].poolInfo[whichBin].poolId, pRealMemory);
+ PORT_ASSERT(retval == 0);
+ }
+ }
+
+ /* PortMemGetPoolSize() : return size of portable memory pool, or 0 if
+ * unknown.
+ */
+ int PortMemBlockGetPoolSize(void)
+ {
+ return 0; /* TODO: Find size of pool: 4Mar02 */
+ }
+
+ /* PortMemBlockSetPoolSize() : set size of portable memory pool on PSOS.
+ * This must be called before PortMemoryInit(), which is called by PortInit().
+ */
+ void PortMemBlockSetPoolSize(size_t sizeInBytes)
+ {}
+
+ int PortMemBlockInit(void)
+ {
+ InitPools();
+ CreatePool(findBin(1 << 3), 3000);
+ CreatePool(findBin(1 << 4), 10000);
+ CreatePool(findBin(1 << 5), 8000);
+ CreatePool(findBin(1 << 6), 16000);
+ CreatePool(findBin(1 << 7), 5000);
+ CreatePool(findBin(1 << 8), 1000);
+ CreatePool(findBin(1 << 9), 2000);
+ CreatePool(findBin(1 << 10), 50);
+ CreatePool(findBin(1 << 11), 20);
+ CreatePool(findBin(1 << 12), 24);
+ CreatePool(findBin(1 << 13), 16);
+ CreatePool(findBin(1 << 14), 10);
+ CreatePool(findBin(1 << 15), 16);
+ CreatePool(findBin(1 << 16), 4);
+ CreatePool(findBin(1 << 18), 6);
+
+ MemoryTrackingInit();
+ }
+
+ void PortMemBlockTerm(void)
+ {
+ TermPools();
+ }
+
+ void PortMemBlockTrackDump(void)
+ {
+ int i;
+
+ printf("\nCurrent Memory Usage = %d\nMaximum Memory Usage = %d\nTotal Memory Allocation = %d\n\n",
+ gMemoryTracking.sCurrentAllocationSize, gMemoryTracking.sMaximumAllocationSize, gMemoryTracking.sTotalAllocationSize);
+
+ printf("\nCurrent Real Memory Usage = %d\nMaximum Real Memory Usage = %d\nTotal Real Memory Allocation = %d\n\n",
+ gMemoryTracking.sCurrentAllocRealSize, gMemoryTracking.sMaximumAllocRealSize, gMemoryTracking.sTotalAllocRealSize);
+
+ for (i = 0; i < NUM_TRACKING_BINS; i++)
+ printf("Max size of 2^%2d byte objects = %d\n", i, gMemoryTracking.sMaximumAllocationSizeArray[i]);
+
+ printf("\nCurrent Memory Objects = %d\nMaximum Memory Objects = %d\nTotal Memory Objects = %d\n\n",
+ gMemoryTracking.sCurrentAllocationNumber, gMemoryTracking.sMaximumAllocationNumber, gMemoryTracking.sTotalAllocationNumber);
+
+ for (i = 0; i < NUM_TRACKING_BINS; i++)
+ printf("Max number for 2^%2d byte objects = %d\n", i, gMemoryTracking.sMaximumAllocationNumberArray[i]);
+ }
+
+ /* PortMemBlockGetMaxMemUsed() : return the maximum real memory allocated.
+ * There is another function of the same name in pmalloc.c, for tracking
+ * non-psos block memory.
+ */
+ int PortMemBlockGetMaxMemUsed(void)
+ {
+ return gMemoryTracking.sMaximumAllocRealSize;
+ }
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PORTABLE_MEM_MGR == PORTABLE_PSOS_BLOCK_SCHEME_MEM_MGR */
+