diff options
Diffstat (limited to 'portable/src/pmemblock.c')
-rw-r--r-- | portable/src/pmemblock.c | 544 |
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 */ + |