diff options
Diffstat (limited to 'portable/src/pmemory_ext.c')
-rw-r--r-- | portable/src/pmemory_ext.c | 369 |
1 files changed, 369 insertions, 0 deletions
diff --git a/portable/src/pmemory_ext.c b/portable/src/pmemory_ext.c new file mode 100644 index 0000000..a30a6cb --- /dev/null +++ b/portable/src/pmemory_ext.c @@ -0,0 +1,369 @@ +/*---------------------------------------------------------------------------* + * pmemory_ext.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 "ptrd.h" +#include "pmutex.h" +#include "passert.h" +#include "pmemory_ext.h" +#include "pmalloc.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +#if defined(USE_THREAD) && defined(USE_DINKUM_LIB_DIRECT) + static MUTEX memextMutex; +#endif + +#ifdef RTXC + void* operator new(size_t size) + { + return (PortNew(size)); + } + void operator delete(void* ptr) + { + PortDelete(ptr); + } +#endif + +#if defined(PORTABLE_DINKUM_MEM_MGR) || defined(PORTABLE_FIXED_SIZE_MEM_BLOCK_SCHEME) + + /* to assist with leak checking */ +static int portNewCount = 0; +static int portDeleteCount = 0; + + /* enable writing and checking of guard words if debugging is enabled */ +#ifdef _DEBUG + /* crash on Xanavi's board with this option on, do not know why */ + /* #define DBG_GUARD_WORDS */ +#endif /* _DEBUG */ + + /* ************************************************************************************ + * PORTABLE_PSOS_BLOCK_SCHEME_MEM_MGR || PORTABLE_DINKUM_MEM_MGR || PORTABLE_FIXED_SIZE_MEM_BLOCK_SCHEME + * ************************************************************************************/ + + /* data ******************************************************************************/ + + static BOOL gMemoryInitted = FALSE; /* TODO: Temporary fix to PortTerm failure */ + +#define MEM_MGR_GetPoolSize() PortMallocGetPoolSize() +#define MEM_MGR_SetPoolSize(sizeInBytes) PortMallocSetPoolSize(sizeInBytes) +#define MEM_MGR_Init() PortMallocInit() +#define MEM_MGR_Term() PortMallocTerm() +#define MEM_MGR_Allocate(sizeInBytes) PortMalloc(sizeInBytes) +#define MEM_MGR_Free(objectPtr) PortFree(objectPtr) +#define MEM_MGR_Dump() +#define MEM_MGR_GetMaxMemUsed() PortMallocGetMaxMemUsed() + + /* guard word data ********************************************************/ + +#ifdef DBG_GUARD_WORDS +#define GUARD_BEGIN 0xbbbbbbbb +#define GUARD_END 0xeeeeeeee + +#define GUARD_OFF_REQ_SIZE 0 +#define GUARD_OFF_START sizeof(unsigned int) +#define GUARD_OFF_PTR (sizeof(unsigned int) + sizeof(unsigned int)) +#define GUARD_EXTRA (sizeof(unsigned int) + sizeof(unsigned int) + sizeof(unsigned int)) +#define GUARD_OFF_END(allocSize) ((allocSize) - sizeof(unsigned int)) +#define GUARD_ALLOC_SIZE(reqSize) ((reqSize)+GUARD_EXTRA) + +#define GUARD_PTR_FIELD(ptr,off) (unsigned int *)((char *)(ptr) + (off)) +#define GUARD_ALLOC_PTR(ptr) (void*) ((char *)(ptr) - GUARD_OFF_PTR) +#endif + + /* scan guard words data **************************************************/ + + /* maintain a static list of allocated blocks (didn't want to perform any dynamic allocation). + * This list can be scanned by PortMemScan() to determine if any allocated blocks + * have overwritten their guard words. + * Calling PortDelete() will check guard words upon de-allocation, but many + * allocated blocks are only freed at program termination, which sometimes doesn't happen. + * + * This software is enabled separately with DBG_SCAN_GUARD_WORDS, because the performance + * overhead is severe. + */ +#ifdef DBG_SCAN_GUARD_WORDS +#define MAX_ALLOCATED_BLOCKS 80000 + static void *allocArray[MAX_ALLOCATED_BLOCKS+1]; + static int allocArrayCount = 0; + + void AddToAllocList(void *memPtr); + void RemoveFromAllocList(void *memPtr); + +#define ADD_TO_ALLOC_LIST(ptr) AddToAllocList(ptr) +#define REMOVE_FROM_ALLOC_LIST(ptr) RemoveFromAllocList(ptr) + +#else +#define ADD_TO_ALLOC_LIST(ptr) +#define REMOVE_FROM_ALLOC_LIST(ptr) +#endif + + /* Guard Functions ********************************************************/ + +#ifdef DBG_SCAN_GUARD_WORDS + /* AddToAllocList() : maintain an array of allocated blocks that can be + * used by PortMemScan() to check for overwritten guard words. + */ + void AddToAllocList(void *memPtr) + { + allocArray[allocArrayCount] = memPtr; + allocArrayCount++; + if (allocArrayCount >= MAX_ALLOCATED_BLOCKS) + { + char buf[256]; + sprintf(buf, "AddToAllocList ERROR : MAX_ALLOCATED_BLOCKS is too small (%d)", allocArrayCount); + PORT_INTERNAL_ERROR(buf); + } + } + + /* RemoveFromAllocList() : maintain an array of allocated blocks that can be + * used by PortMemScan() to check for overwritten guard words. + */ + void RemoveFromAllocList(void *memPtr) + { + int i; /* loop index */ + int j; /* loop index */ + int inList = FALSE; /* TRUE when found in list */ + + for (i = 0; i < allocArrayCount; i++) + { + if (allocArray[i] == memPtr) + { + inList = TRUE; + break; + } + } + PORT_ASSERT(inList == TRUE); /* MUST be in list */ + /* remove by sliding down all following entries */ + for (j = i + 1; j < allocArrayCount; j++) + allocArray[j-1] = allocArray[j]; + allocArrayCount--; + allocArray[allocArrayCount] = NULL; /* clear out end of list */ + } + + /* PortMemScan() : scan the array of allocated blocks, confirming that no + * allocated block has overwritten its guard words. + */ + void PortMemScan(void) + { + int i; + + PortCriticalSectionEnter(&PortMemoryCriticalSection); + + /* scan the allocated memory list */ + for (i = 0; i < allocArrayCount; i++) + { + /* verify that guard words have not been corrupted */ + void *memPtr = allocArray[i]; + void *allocPtr = GUARD_ALLOC_PTR(memPtr); + unsigned int *requestedSizePtr = GUARD_PTR_FIELD(allocPtr, GUARD_OFF_REQ_SIZE); + unsigned int *guardStartPtr = GUARD_PTR_FIELD(allocPtr, GUARD_OFF_START); + unsigned int *guardEndPtr = GUARD_PTR_FIELD(allocPtr, GUARD_OFF_END(GUARD_ALLOC_SIZE(*requestedSizePtr))); + + if ((*guardStartPtr) != GUARD_BEGIN) + { + PLogError("PortMemScan : corrupted start guard from block 0x%08x \n", (int)memPtr); + } + if ((*guardEndPtr) != GUARD_END) + { + PLogError("PortMemScan : corrupted end guard from block 0x%08x \n", (int)memPtr); + } + } + + PortCriticalSectionLeave(&PortMemoryCriticalSection); + } +#endif /* DBG_SCAN_GUARD_WORDS */ + + /* Port Memory Functions ******************************************************/ + + /* PortMemGetPoolSize() : return size of portable memory pool, or 0 if + * unknown. + */ + int PortMemGetPoolSize(void) + { + return MEM_MGR_GetPoolSize(); + } + + /* PortMemSetPoolSize() : set size of portable memory pool on PSOS. + * This must be called before PortMemoryInit(), which is called by PortInit(). + */ + void PortMemSetPoolSize(size_t sizeInBytes) + { + MEM_MGR_SetPoolSize(sizeInBytes); + } + + /* PortMemoryInit() : + */ + + int PortMemoryInit(void) + { +#if defined(USE_THREAD) && defined(USE_DINKUM_LIB_DIRECT) + if (createMutex(&memextMutex) == ESR_SUCCESS) +#endif + { + if (!gMemoryInitted) + { + MEM_MGR_Init(); + gMemoryInitted = TRUE; + } + } + + return gMemoryInitted; + } + + /* PortMemoryTerm() : + */ + + void PortMemoryTerm(void) + { + /* TODO: MEM_PSOS_BLOCK_SCHEME + * Figure out why free memory causes rn#0 is get messed up! */ + MEM_MGR_Term(); +#if defined(USE_THREAD) && defined(USE_DINKUM_LIB_DIRECT) + deleteMutex(&memextMutex); +#endif + gMemoryInitted = FALSE; + } + + /* PortNew() : + */ + + void* PortNew(size_t sizeInBytes) + { + if (gMemoryInitted) + { + void *pMemory = NULL; + +#if defined(USE_THREAD) && defined(USE_DINKUM_LIB_DIRECT) + lockMutex(&memextMutex); +#endif + portNewCount++; + +#ifdef DBG_GUARD_WORDS + sizeInBytes += GUARD_EXTRA; /* space for: requestedSize,guardStart,guardEnd */ +#endif + + pMemory = MEM_MGR_Allocate(sizeInBytes); + +#ifdef DBG_GUARD_WORDS + if (NULL != pMemory) + { + /* at the beginning of the buffer, store the requested size and a guard word. + * Store another guard word at the end of the buffer. + */ + /* set guard words at either end of allocated buffer; will be checked at delete time */ + unsigned int * requestedSizePtr = GUARD_PTR_FIELD(pMemory, GUARD_OFF_REQ_SIZE); + unsigned int * guardStartPtr = GUARD_PTR_FIELD(pMemory, GUARD_OFF_START); + unsigned int * guardEndPtr = GUARD_PTR_FIELD(pMemory, GUARD_OFF_END(sizeInBytes)); + + *requestedSizePtr = sizeInBytes - GUARD_EXTRA; + *guardStartPtr = GUARD_BEGIN; + *guardEndPtr = GUARD_END; + pMemory = (void *) GUARD_PTR_FIELD(pMemory, GUARD_OFF_PTR); + ADD_TO_ALLOC_LIST(pMemory); + } +#endif /* DBG_GUARD_WORDS */ +#if defined(USE_THREAD) && defined(USE_DINKUM_LIB_DIRECT) + unlockMutex(&memextMutex); +#endif + return pMemory; + } +#ifdef PSOSIM + /* PSOSIM's license manager calls new() before PSOS is running */ + else + { + return(malloc(sizeInBytes)); + } +#else /* PSOSIM */ + /* Memory allocator not initialized when request for memory was made */ + passert(FALSE && "Call PortInit() before calling any portable functions\r\n"); + return NULL; +#endif /* PSOSIM */ + } + + void PortDelete(void* objectPtr) + { +#if defined(USE_THREAD) && defined(USE_DINKUM_LIB_DIRECT) + lockMutex(&memextMutex); +#endif + portDeleteCount++; + +#ifdef DBG_GUARD_WORDS + { + /* verify that guard words have not been corrupted */ + void *allocPtr = GUARD_ALLOC_PTR(objectPtr); + unsigned int *requestedSizePtr = GUARD_PTR_FIELD(allocPtr, GUARD_OFF_REQ_SIZE); + unsigned int *guardStartPtr = GUARD_PTR_FIELD(allocPtr, GUARD_OFF_START); + unsigned int *guardEndPtr = GUARD_PTR_FIELD(allocPtr, GUARD_OFF_END(GUARD_ALLOC_SIZE(*requestedSizePtr))); + + passert((*guardStartPtr) == GUARD_BEGIN); + passert((*guardEndPtr) == GUARD_END); + REMOVE_FROM_ALLOC_LIST(allocPtr); + objectPtr = allocPtr; + } +#endif + + MEM_MGR_Free(objectPtr); +#if defined(USE_THREAD) && defined(USE_DINKUM_LIB_DIRECT) + unlockMutex(&memextMutex); +#endif + } + + void PortMemTrackDump(void) + { + MEM_MGR_Dump(); + } + + /* PortGetMaxMemUsed() : return the maximum real memory allocated. + * There is another function of the same name in pmalloc.c, for tracking + * non-psos block memory. It uses #ifndef MEM_PSOS_BLOCK_SCHEME to enable. + */ + int PortGetMaxMemUsed(void) + { + return MEM_MGR_GetMaxMemUsed(); + } + + /* PortMemCntReset() : reset the New/Delete count. + * This is useful for checking that each new has a corresponding delete once + * the system gets into a steady state. + */ + void PortMemCntReset() + { + portNewCount = 0; + portDeleteCount = 0; + } + + + /* PortMemGetCount() : return the accumulated new & delete counts */ + void PortMemGetCount(int *newCount, int *deleteCount) + { + *newCount = portNewCount; + *deleteCount = portDeleteCount; + } + +#endif /* (==PORTABLE_PSOS_BLOCK_SCHEME_MEM_MGR) || (==PORTABLE_DINKUM_MEM_MGR) || (==PORTABLE_FIXED_SIZE_MEM_BLOCK_SCHEME) */ + +#ifdef __cplusplus +} +#endif |