/****************************************************************************** *_Copyright (c) 2009 Digital Stream Technology Inc. All Rights Reserved. * * Module: memchain.c * * Description * Utility for associating allocated memory * ******************************************************************************/ #include "dsthalcommon.h" #include "dsthalPsiMemChain.h" #include #include #ifdef DMALLOC #include #endif #define MAX_FUNC_NAME 32 // Çã¿ëÇÒ ÃÖ´ë ÇÔ¼ö À̸§ ±æÀÌ #define MAX_COUNT 5000 // °ü¸®ÇÒ °¹¼ö static struct MEM_LIST { char func[MAX_FUNC_NAME+1]; int nLine; void *p; int nSize; unsigned int tick; } memlist[MAX_COUNT]; void Print_MemChain_MemUnit(void) { int i = 0, nSum = 0, nCount = 0; printf("|------------+----------+----------------------------------+------|\n"); printf("| Address | Size | Function | Line |\n"); printf("|------------+----------+----------------------------------+------|\n"); for (i = 0; i < MAX_COUNT; i++) { if (memlist[i].p == 0) continue; printf("| 0x%08X | %8d | %32s | %4d | %4ld |\n", (int)memlist[i].p, memlist[i].nSize, memlist[i].func, memlist[i].nLine, (OS_GetTickCount() - memlist[i].tick)/100 ); nSum+=memlist[i].nSize; nCount++; } printf("|------------+----------+----------------------------------+------|\n"); printf("| %10d | %8d | |\n", nCount, nSum); printf("|------------+----------+----------------------------------+------|\n"); } static void Add_MemUint(char* func, int nLine, void *p, int nSize) { int i = 0; for (i = 0; i < MAX_COUNT; i++) { if (memlist[i].p != 0) continue; if (strlen(func) > MAX_FUNC_NAME) { memcpy(memlist[i].func, func, MAX_FUNC_NAME); memlist[i].func[MAX_FUNC_NAME] = 0; } else { strcpy(memlist[i].func, func); } memlist[i].nLine = nLine; memlist[i].p = p; memlist[i].nSize = nSize; memlist[i].tick = OS_GetTickCount(); break; } //Print_MemUnit(); } static void Del_MemUnit(void *p, const char * func, int nLine) { int i = 0; if (p == 0) return; for (i = 0; i < MAX_COUNT; i++) { if (memlist[i].p != p) continue; memlist[i].p = 0; break; } if (i >= MAX_COUNT) { #if 0 printf("\n\n\n\nTry to delete unallocated memory 0x%08X. %s %d\n\n\n", (int)p, func, nLine); Print_All_MemUnit(); OS_Delay(5); #endif } //Print_MemUnit(); } static int nCount = 0; int print_memchain_malloc() { return nCount; } static void *memchain_malloc(unsigned int size, char* func, int nLine) { void *p = 0; nCount++; p = OS_malloc2(size); Add_MemUint(func, nLine, p, size); // printf("nCount = %d adde = %08X\n", nCount, p); return p; } static void memchain_free(void *p, const char *func, int nLine) { nCount--; // printf("nCount = %d adde = %08X\n", nCount, p); Del_MemUnit(p, func, nLine); OS_free2(p); } /****************************************************************************** * Global variable declaration ******************************************************************************/ /****************************************************************************** * Imported variable declaration ******************************************************************************/ /****************************************************************************** * Imported function declaration ******************************************************************************/ /****************************************************************************** * Local definitions ******************************************************************************/ #define MEMCHAIN_MAGIC 0x45CBA9D1 /****************************************************************************** * Local typedefs ******************************************************************************/ typedef struct memElement { void* userData; struct memElement *next; } memElement_t, *memElementPtr_t; typedef struct memChainHead { DS_U32 magic; DS_U32 memLimit; myMalloc_f Malloc; myFree_f Free; DS_U32 totalElements; DS_U32 totalBytes; DS_U32 totalUserBytes; memElementPtr_t element; } memChainHead_t, *memChainHeadPtr_t; /****************************************************************************** * Local variables declaration ******************************************************************************/ /****************************************************************************** * Local function prototypes ******************************************************************************/ /*========================================================================= ErrCode memChainCreate (memId_t *memId, memChainSetupPtr_t setupPtr) *memId: memId of the newly created memChain. setupPtr: Pointer to the memChain setup information. Creates a memChain object which links related memory into a 'chain'. All memory associated with this chain can then be easily freed. =========================================================================*/ DHL_RESULT _memChainCreate (memId_t *memId, memChainSetupPtr_t setupPtr, const char *func, int nLine) { myMalloc_f Malloc; memChainHeadPtr_t memChainHeadPtr; DHL_RESULT err = DHL_OK; if ((memId == NULL) || setupPtr == NULL) { err = DHL_FAIL_INVALID_PARAM; goto memChainCreateEnd; } if (setupPtr->Malloc == NULL) { Malloc = (myMalloc_f)memchain_malloc; } else { Malloc = (myMalloc_f)(setupPtr->Malloc); } memChainHeadPtr = (memChainHeadPtr_t)Malloc(sizeof(memChainHead_t), func, nLine); if (memChainHeadPtr == NULL) { err = DHL_FAIL_OUT_OF_RESOURCE; goto memChainCreateEnd; } memset(memChainHeadPtr,0x00,sizeof(memChainHead_t)); /* initialize */ memChainHeadPtr->memLimit = setupPtr->memLimit; memChainHeadPtr->Malloc = Malloc; if (setupPtr->Free == NULL) { memChainHeadPtr->Free = memchain_free; } else { memChainHeadPtr->Free = setupPtr->Free; } memChainHeadPtr->magic = MEMCHAIN_MAGIC; memChainHeadPtr->totalElements = 0; memChainHeadPtr->totalBytes = sizeof(memChainHead_t); memChainHeadPtr->totalUserBytes = 0; memChainHeadPtr->element = NULL; /* set instance */ *memId = memChainHeadPtr; memChainCreateEnd: return (err); } /*========================================================================= DHL_RESULT memChainDestroy (memId_t memId) memId: memId of the memChain. Destroys the memChain, freeing all associated memory. =========================================================================*/ DHL_RESULT _memChainDestroy (memId_t memId, const char *func, int nLine) { memChainHeadPtr_t memChainHeadPtr = (memChainHeadPtr_t)memId; memElementPtr_t currElem, prevElem; memChainHeadPtr->magic = 0; /* free the memElements */ currElem = memChainHeadPtr->element; while (currElem != NULL) { prevElem = currElem; currElem = currElem->next; memChainHeadPtr->Free(prevElem , func, nLine); } /* lastly, free the memChainHead */ memChainHeadPtr->Free(memChainHeadPtr , func, nLine); return (DHL_OK); } /*========================================================================= void* memChainAlloc (memId_t memId, DS_U32 size) memId: memId of the memChain. size: The size of the requested memory chunk. Allocates a memory block of the requested size and associates it with the specified memChain. Returns NULL if the OS_Calloc() fails or if memLimit will be exceeded. =========================================================================*/ void* _memChainAlloc (memId_t memId, DS_U32 size, const char *func, int nLine) { memChainHeadPtr_t memChainHeadPtr = (memChainHeadPtr_t)memId; memElementPtr_t memElementPtr; DS_U32 allocSize; void *rptr, *p; /* check the memLimit (memLimit = 0 means no limit) */ if (memChainHeadPtr->memLimit > 0) { if (memChainHeadPtr->totalUserBytes + size > memChainHeadPtr->memLimit) { if ( memChainHeadPtr->memLimit > 0x10000 ) { printf("%s:%d->| memLimit exceeded. memId=0x%08lX, totalUserBytes=%ld (+%ld), memLimit = %ld\n", func, nLine, (DS_U32)memId, memChainHeadPtr->totalUserBytes, size, memChainHeadPtr->memLimit); Print_MemChain_MemUnit(); rptr = NULL; goto memChainAllocEnd; } else { memChainHeadPtr->memLimit *= 2; } } } /* allocate the memory - add 8 bytes to guarantee 64-bit alignment of user data */ allocSize = sizeof(memElement_t) + size + 8; memElementPtr = (memElementPtr_t)memChainHeadPtr->Malloc(allocSize,func,nLine); if (memElementPtr == NULL) { rptr = NULL; goto memChainAllocEnd; } memset(memElementPtr,0x00,allocSize); p = (void *)(((DS_U8 *)(memElementPtr) + sizeof(memElement_t))); /* align on 64-bit boundary */ memElementPtr->userData = (void *)((DS_U32)(((DS_U8 *)p)+8) & ((~0) << 3)); rptr = memElementPtr->userData; /* insert element in list */ memElementPtr->next = memChainHeadPtr->element; memChainHeadPtr->element = memElementPtr; /* update tracking statistics */ memChainHeadPtr->totalElements++; memChainHeadPtr->totalBytes += allocSize; memChainHeadPtr->totalUserBytes += size; memChainAllocEnd: return (rptr); }