| 1 | /****************************************************************************** |
|---|
| 2 | *_Copyright (c) 2009 Digital Stream Technology Inc. All Rights Reserved. |
|---|
| 3 | * |
|---|
| 4 | * Module: memchain.c |
|---|
| 5 | * |
|---|
| 6 | * Description |
|---|
| 7 | * Utility for associating allocated memory |
|---|
| 8 | * |
|---|
| 9 | ******************************************************************************/ |
|---|
| 10 | |
|---|
| 11 | #include "dsthalcommon.h" |
|---|
| 12 | #include "dsthalPsiMemChain.h" |
|---|
| 13 | |
|---|
| 14 | #include <stdlib.h> |
|---|
| 15 | #include <string.h> |
|---|
| 16 | |
|---|
| 17 | #ifdef DMALLOC |
|---|
| 18 | #include <dmalloc.h> |
|---|
| 19 | #endif |
|---|
| 20 | |
|---|
| 21 | |
|---|
| 22 | #define MAX_FUNC_NAME 32 // Çã¿ëÇÒ ÃÖ´ë ÇÔ¼ö À̸§ ±æÀÌ |
|---|
| 23 | #define MAX_COUNT 5000 // °ü¸®ÇÒ °¹¼ö |
|---|
| 24 | |
|---|
| 25 | static struct MEM_LIST |
|---|
| 26 | { |
|---|
| 27 | char func[MAX_FUNC_NAME+1]; |
|---|
| 28 | int nLine; |
|---|
| 29 | void *p; |
|---|
| 30 | int nSize; |
|---|
| 31 | unsigned int tick; |
|---|
| 32 | } memlist[MAX_COUNT]; |
|---|
| 33 | |
|---|
| 34 | void Print_MemChain_MemUnit(void) |
|---|
| 35 | { |
|---|
| 36 | int i = 0, nSum = 0, nCount = 0; |
|---|
| 37 | printf("|------------+----------+----------------------------------+------|\n"); |
|---|
| 38 | printf("| Address | Size | Function | Line |\n"); |
|---|
| 39 | printf("|------------+----------+----------------------------------+------|\n"); |
|---|
| 40 | for (i = 0; i < MAX_COUNT; i++) |
|---|
| 41 | { |
|---|
| 42 | if (memlist[i].p == 0) continue; |
|---|
| 43 | 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 ); |
|---|
| 44 | nSum+=memlist[i].nSize; |
|---|
| 45 | nCount++; |
|---|
| 46 | } |
|---|
| 47 | printf("|------------+----------+----------------------------------+------|\n"); |
|---|
| 48 | printf("| %10d | %8d | |\n", nCount, nSum); |
|---|
| 49 | printf("|------------+----------+----------------------------------+------|\n"); |
|---|
| 50 | } |
|---|
| 51 | |
|---|
| 52 | static void Add_MemUint(char* func, int nLine, void *p, int nSize) |
|---|
| 53 | { |
|---|
| 54 | int i = 0; |
|---|
| 55 | for (i = 0; i < MAX_COUNT; i++) |
|---|
| 56 | { |
|---|
| 57 | if (memlist[i].p != 0) continue; |
|---|
| 58 | if (strlen(func) > MAX_FUNC_NAME) |
|---|
| 59 | { |
|---|
| 60 | memcpy(memlist[i].func, func, MAX_FUNC_NAME); |
|---|
| 61 | memlist[i].func[MAX_FUNC_NAME] = 0; |
|---|
| 62 | } |
|---|
| 63 | else |
|---|
| 64 | { |
|---|
| 65 | strcpy(memlist[i].func, func); |
|---|
| 66 | } |
|---|
| 67 | memlist[i].nLine = nLine; |
|---|
| 68 | memlist[i].p = p; |
|---|
| 69 | memlist[i].nSize = nSize; |
|---|
| 70 | memlist[i].tick = OS_GetTickCount(); |
|---|
| 71 | break; |
|---|
| 72 | } |
|---|
| 73 | //Print_MemUnit(); |
|---|
| 74 | } |
|---|
| 75 | |
|---|
| 76 | |
|---|
| 77 | static void Del_MemUnit(void *p, const char * func, int nLine) |
|---|
| 78 | { |
|---|
| 79 | int i = 0; |
|---|
| 80 | if (p == 0) return; |
|---|
| 81 | for (i = 0; i < MAX_COUNT; i++) |
|---|
| 82 | { |
|---|
| 83 | if (memlist[i].p != p) continue; |
|---|
| 84 | memlist[i].p = 0; |
|---|
| 85 | break; |
|---|
| 86 | } |
|---|
| 87 | if (i >= MAX_COUNT) |
|---|
| 88 | { |
|---|
| 89 | #if 0 |
|---|
| 90 | printf("\n\n\n\nTry to delete unallocated memory 0x%08X. %s %d\n\n\n", (int)p, func, nLine); |
|---|
| 91 | Print_All_MemUnit(); |
|---|
| 92 | OS_Delay(5); |
|---|
| 93 | #endif |
|---|
| 94 | } |
|---|
| 95 | //Print_MemUnit(); |
|---|
| 96 | } |
|---|
| 97 | |
|---|
| 98 | |
|---|
| 99 | static int nCount = 0; |
|---|
| 100 | int print_memchain_malloc() |
|---|
| 101 | { |
|---|
| 102 | return nCount; |
|---|
| 103 | } |
|---|
| 104 | static void *memchain_malloc(unsigned int size, char* func, int nLine) |
|---|
| 105 | { |
|---|
| 106 | void *p = 0; |
|---|
| 107 | nCount++; |
|---|
| 108 | p = OS_malloc2(size); |
|---|
| 109 | Add_MemUint(func, nLine, p, size); |
|---|
| 110 | |
|---|
| 111 | // printf("nCount = %d adde = %08X\n", nCount, p); |
|---|
| 112 | return p; |
|---|
| 113 | } |
|---|
| 114 | |
|---|
| 115 | static void memchain_free(void *p, const char *func, int nLine) |
|---|
| 116 | { |
|---|
| 117 | nCount--; |
|---|
| 118 | // printf("nCount = %d adde = %08X\n", nCount, p); |
|---|
| 119 | Del_MemUnit(p, func, nLine); |
|---|
| 120 | OS_free2(p); |
|---|
| 121 | } |
|---|
| 122 | /****************************************************************************** |
|---|
| 123 | * Global variable declaration |
|---|
| 124 | ******************************************************************************/ |
|---|
| 125 | |
|---|
| 126 | |
|---|
| 127 | /****************************************************************************** |
|---|
| 128 | * Imported variable declaration |
|---|
| 129 | ******************************************************************************/ |
|---|
| 130 | |
|---|
| 131 | |
|---|
| 132 | /****************************************************************************** |
|---|
| 133 | * Imported function declaration |
|---|
| 134 | ******************************************************************************/ |
|---|
| 135 | |
|---|
| 136 | |
|---|
| 137 | /****************************************************************************** |
|---|
| 138 | * Local definitions |
|---|
| 139 | ******************************************************************************/ |
|---|
| 140 | #define MEMCHAIN_MAGIC 0x45CBA9D1 |
|---|
| 141 | |
|---|
| 142 | /****************************************************************************** |
|---|
| 143 | * Local typedefs |
|---|
| 144 | ******************************************************************************/ |
|---|
| 145 | typedef struct memElement { |
|---|
| 146 | void* userData; |
|---|
| 147 | struct memElement *next; |
|---|
| 148 | } memElement_t, *memElementPtr_t; |
|---|
| 149 | |
|---|
| 150 | typedef struct memChainHead { |
|---|
| 151 | DS_U32 magic; |
|---|
| 152 | DS_U32 memLimit; |
|---|
| 153 | myMalloc_f Malloc; |
|---|
| 154 | myFree_f Free; |
|---|
| 155 | DS_U32 totalElements; |
|---|
| 156 | DS_U32 totalBytes; |
|---|
| 157 | DS_U32 totalUserBytes; |
|---|
| 158 | memElementPtr_t element; |
|---|
| 159 | } memChainHead_t, *memChainHeadPtr_t; |
|---|
| 160 | |
|---|
| 161 | /****************************************************************************** |
|---|
| 162 | * Local variables declaration |
|---|
| 163 | ******************************************************************************/ |
|---|
| 164 | |
|---|
| 165 | |
|---|
| 166 | /****************************************************************************** |
|---|
| 167 | * Local function prototypes |
|---|
| 168 | ******************************************************************************/ |
|---|
| 169 | |
|---|
| 170 | /*========================================================================= |
|---|
| 171 | ErrCode memChainCreate (memId_t *memId, memChainSetupPtr_t setupPtr) |
|---|
| 172 | |
|---|
| 173 | *memId: memId of the newly created memChain. |
|---|
| 174 | setupPtr: Pointer to the memChain setup information. |
|---|
| 175 | |
|---|
| 176 | Creates a memChain object which links related memory into a 'chain'. All |
|---|
| 177 | memory associated with this chain can then be easily freed. |
|---|
| 178 | =========================================================================*/ |
|---|
| 179 | DHL_RESULT _memChainCreate (memId_t *memId, memChainSetupPtr_t setupPtr, const char *func, int nLine) |
|---|
| 180 | { |
|---|
| 181 | myMalloc_f Malloc; |
|---|
| 182 | memChainHeadPtr_t memChainHeadPtr; |
|---|
| 183 | DHL_RESULT err = DHL_OK; |
|---|
| 184 | |
|---|
| 185 | if ((memId == NULL) || setupPtr == NULL) { |
|---|
| 186 | err = DHL_FAIL_INVALID_PARAM; |
|---|
| 187 | goto memChainCreateEnd; |
|---|
| 188 | } |
|---|
| 189 | |
|---|
| 190 | if (setupPtr->Malloc == NULL) { |
|---|
| 191 | Malloc = (myMalloc_f)memchain_malloc; |
|---|
| 192 | } |
|---|
| 193 | else { |
|---|
| 194 | Malloc = (myMalloc_f)(setupPtr->Malloc); |
|---|
| 195 | } |
|---|
| 196 | memChainHeadPtr = (memChainHeadPtr_t)Malloc(sizeof(memChainHead_t), func, nLine); |
|---|
| 197 | if (memChainHeadPtr == NULL) { |
|---|
| 198 | err = DHL_FAIL_OUT_OF_RESOURCE; |
|---|
| 199 | goto memChainCreateEnd; |
|---|
| 200 | } |
|---|
| 201 | memset(memChainHeadPtr,0x00,sizeof(memChainHead_t)); |
|---|
| 202 | |
|---|
| 203 | /* initialize */ |
|---|
| 204 | memChainHeadPtr->memLimit = setupPtr->memLimit; |
|---|
| 205 | memChainHeadPtr->Malloc = Malloc; |
|---|
| 206 | if (setupPtr->Free == NULL) { |
|---|
| 207 | memChainHeadPtr->Free = memchain_free; |
|---|
| 208 | } |
|---|
| 209 | else { |
|---|
| 210 | memChainHeadPtr->Free = setupPtr->Free; |
|---|
| 211 | } |
|---|
| 212 | memChainHeadPtr->magic = MEMCHAIN_MAGIC; |
|---|
| 213 | memChainHeadPtr->totalElements = 0; |
|---|
| 214 | memChainHeadPtr->totalBytes = sizeof(memChainHead_t); |
|---|
| 215 | memChainHeadPtr->totalUserBytes = 0; |
|---|
| 216 | memChainHeadPtr->element = NULL; |
|---|
| 217 | |
|---|
| 218 | /* set instance */ |
|---|
| 219 | *memId = memChainHeadPtr; |
|---|
| 220 | |
|---|
| 221 | memChainCreateEnd: |
|---|
| 222 | return (err); |
|---|
| 223 | } |
|---|
| 224 | |
|---|
| 225 | |
|---|
| 226 | /*========================================================================= |
|---|
| 227 | DHL_RESULT memChainDestroy (memId_t memId) |
|---|
| 228 | |
|---|
| 229 | memId: memId of the memChain. |
|---|
| 230 | |
|---|
| 231 | Destroys the memChain, freeing all associated memory. |
|---|
| 232 | =========================================================================*/ |
|---|
| 233 | DHL_RESULT _memChainDestroy (memId_t memId, const char *func, int nLine) |
|---|
| 234 | { |
|---|
| 235 | memChainHeadPtr_t memChainHeadPtr = (memChainHeadPtr_t)memId; |
|---|
| 236 | memElementPtr_t currElem, prevElem; |
|---|
| 237 | |
|---|
| 238 | memChainHeadPtr->magic = 0; |
|---|
| 239 | |
|---|
| 240 | /* free the memElements */ |
|---|
| 241 | currElem = memChainHeadPtr->element; |
|---|
| 242 | while (currElem != NULL) { |
|---|
| 243 | prevElem = currElem; |
|---|
| 244 | currElem = currElem->next; |
|---|
| 245 | memChainHeadPtr->Free(prevElem , func, nLine); |
|---|
| 246 | } |
|---|
| 247 | |
|---|
| 248 | /* lastly, free the memChainHead */ |
|---|
| 249 | memChainHeadPtr->Free(memChainHeadPtr , func, nLine); |
|---|
| 250 | |
|---|
| 251 | return (DHL_OK); |
|---|
| 252 | } |
|---|
| 253 | |
|---|
| 254 | |
|---|
| 255 | /*========================================================================= |
|---|
| 256 | void* memChainAlloc (memId_t memId, DS_U32 size) |
|---|
| 257 | |
|---|
| 258 | memId: memId of the memChain. |
|---|
| 259 | size: The size of the requested memory chunk. |
|---|
| 260 | |
|---|
| 261 | Allocates a memory block of the requested size and associates it with the |
|---|
| 262 | specified memChain. Returns NULL if the OS_Calloc() fails or if memLimit |
|---|
| 263 | will be exceeded. |
|---|
| 264 | =========================================================================*/ |
|---|
| 265 | void* _memChainAlloc (memId_t memId, DS_U32 size, const char *func, int nLine) |
|---|
| 266 | { |
|---|
| 267 | memChainHeadPtr_t memChainHeadPtr = (memChainHeadPtr_t)memId; |
|---|
| 268 | memElementPtr_t memElementPtr; |
|---|
| 269 | DS_U32 allocSize; |
|---|
| 270 | void *rptr, *p; |
|---|
| 271 | |
|---|
| 272 | /* check the memLimit (memLimit = 0 means no limit) */ |
|---|
| 273 | if (memChainHeadPtr->memLimit > 0) { |
|---|
| 274 | if (memChainHeadPtr->totalUserBytes + size > memChainHeadPtr->memLimit) { |
|---|
| 275 | if ( memChainHeadPtr->memLimit > 0x10000 ) |
|---|
| 276 | { |
|---|
| 277 | printf("%s:%d->| memLimit exceeded. memId=0x%08lX, totalUserBytes=%ld (+%ld), memLimit = %ld\n", func, nLine, (DS_U32)memId, memChainHeadPtr->totalUserBytes, size, memChainHeadPtr->memLimit); |
|---|
| 278 | Print_MemChain_MemUnit(); |
|---|
| 279 | rptr = NULL; |
|---|
| 280 | goto memChainAllocEnd; |
|---|
| 281 | } |
|---|
| 282 | else |
|---|
| 283 | { |
|---|
| 284 | memChainHeadPtr->memLimit *= 2; |
|---|
| 285 | } |
|---|
| 286 | } |
|---|
| 287 | } |
|---|
| 288 | |
|---|
| 289 | /* allocate the memory - add 8 bytes to guarantee 64-bit alignment of user data */ |
|---|
| 290 | allocSize = sizeof(memElement_t) + size + 8; |
|---|
| 291 | |
|---|
| 292 | memElementPtr = (memElementPtr_t)memChainHeadPtr->Malloc(allocSize,func,nLine); |
|---|
| 293 | if (memElementPtr == NULL) { |
|---|
| 294 | rptr = NULL; |
|---|
| 295 | goto memChainAllocEnd; |
|---|
| 296 | } |
|---|
| 297 | memset(memElementPtr,0x00,allocSize); |
|---|
| 298 | |
|---|
| 299 | p = (void *)(((DS_U8 *)(memElementPtr) + sizeof(memElement_t))); |
|---|
| 300 | |
|---|
| 301 | /* align on 64-bit boundary */ |
|---|
| 302 | memElementPtr->userData = (void *)((DS_U32)(((DS_U8 *)p)+8) & ((~0) << 3)); |
|---|
| 303 | rptr = memElementPtr->userData; |
|---|
| 304 | |
|---|
| 305 | /* insert element in list */ |
|---|
| 306 | memElementPtr->next = memChainHeadPtr->element; |
|---|
| 307 | memChainHeadPtr->element = memElementPtr; |
|---|
| 308 | |
|---|
| 309 | /* update tracking statistics */ |
|---|
| 310 | memChainHeadPtr->totalElements++; |
|---|
| 311 | memChainHeadPtr->totalBytes += allocSize; |
|---|
| 312 | memChainHeadPtr->totalUserBytes += size; |
|---|
| 313 | |
|---|
| 314 | memChainAllocEnd: |
|---|
| 315 | return (rptr); |
|---|
| 316 | } |
|---|