void *cmsMem_realloc(void *origBuf, UINT32 size) { void *buf; UINT32 origSize, origAllocSize, origAllocFlags; UINT32 allocSize; UINT32 *intBuf; if (origBuf == NULL) { cmsLog_error("cannot take a NULL buffer"); return NULL; } if (size == 0) { cmsMem_free(origBuf); return NULL; } allocSize = REAL_ALLOC_SIZE(size); intBuf = (UINT32 *) (((UINT32) origBuf) - CMS_MEM_HEADER_LENGTH); origAllocFlags = intBuf[0]; origSize = intBuf[1]; /* sanity check the original length */ if (intBuf[1] != (intBuf[2] ^ 0xffffffff)) { cmsLog_error("memory underflow detected, %d %d", intBuf[1], intBuf[2]); cmsAst_assert(0); return NULL; } origAllocSize = REAL_ALLOC_SIZE(origSize); if (allocSize <= origAllocSize) { /* currently, I don't shrink buffers, but could in the future. */ return origBuf; } buf = cmsMem_alloc(allocSize, origAllocFlags); if (buf != NULL) { /* got new buffer, copy orig buffer to new buffer */ memcpy(buf, origBuf, origSize); cmsMem_free(origBuf); } else { /* * We could not allocate a bigger buffer. * Return NULL but leave the original buffer untouched. */ } return buf; }
/** Free previously allocated memory * @param buf Previously allocated buffer. */ void cmsMem_free(void *buf) { UINT32 size; if (buf != NULL) { UINT32 *intBuf = (UINT32 *) (((UINT32) buf) - CMS_MEM_HEADER_LENGTH); #ifdef CMS_MEM_LEAK_TRACING { AllocRecord *allocRec; dlist_for_each_entry(allocRec, &glbAllocRec, dlist) if (allocRec->bufAddr == buf) break; if ((DlistNode *) allocRec != &glbAllocRec) { dlist_unlink((struct dlist_node *) allocRec); free(allocRec); } else { /* * Buffers allocated from shared mem could have been freed by * another app, so if we have an alloc record but cannot find * it in shared mem, ignore it. But if the alloc record is in * private heap, that is an error. */ if (!IS_IN_SHARED_MEM(buf)) { cmsLog_error("possible double free, could not find allocRec for buf %p", buf); } } } #endif size = intBuf[1]; if (intBuf[1] != (intBuf[2] ^ 0xffffffff)) { cmsLog_error("memory underflow detected, %d %d", intBuf[1], intBuf[2]); cmsAst_assert(0); return; } #ifdef CMS_MEM_DEBUG { UINT32 allocSize, intSize, roundup4Size, i; UINT8 *charBuf = (UINT8 *) buf; allocSize = REAL_ALLOC_SIZE(intBuf[1]); intSize = allocSize / sizeof(UINT32); roundup4Size = ROUNDUP4(intBuf[1]); for (i=intBuf[1]; i < roundup4Size; i++) { if (charBuf[i] != (UINT8) (CMS_MEM_FOOTER_PATTERN & 0xff)) { cmsLog_error("memory overflow detected at idx=%d 0x%x 0x%x 0x%x", i, charBuf[i], intBuf[intSize-1], intBuf[intSize-2]); cmsAst_assert(0); return; } } if ((intBuf[intSize - 1] != CMS_MEM_FOOTER_PATTERN) || (intBuf[intSize - 2] != CMS_MEM_FOOTER_PATTERN)) { cmsLog_error("memory overflow detected, 0x%x 0x%x", intBuf[intSize - 1], intBuf[intSize - 2]); cmsAst_assert(0); return; } #ifdef CMS_MEM_POISON_ALLOC_FREE /* * write garbage into buffer which is about to be freed to detect * users of freed buffers. */ memset(intBuf, CMS_MEM_FREE_PATTERN, allocSize); #endif } #endif /* CMS_MEM_DEBUG */ buf = intBuf; /* buf points to real start of buffer */ #ifdef MDM_SHARED_MEM if (IS_IN_SHARED_MEM(buf)) { brel(buf); } else #endif { oal_free(buf); mStats.bytesAllocd -= size; mStats.numFrees++; } }
void *cmsMem_alloc(UINT32 size, UINT32 allocFlags) { void *buf; UINT32 allocSize; #ifdef CMS_MEM_LEAK_TRACING initAllocSeq(); #endif allocSize = REAL_ALLOC_SIZE(size); #ifdef MDM_SHARED_MEM if (allocFlags & ALLOC_SHARED_MEM) { #ifdef CMS_MEM_LEAK_TRACING buf = bget(allocSize, allocSeq); #else buf = bget(allocSize); #endif } else #endif { buf = oal_malloc(allocSize); if (buf) { mStats.bytesAllocd += size; mStats.numAllocs++; } } if (buf != NULL) { UINT32 *intBuf = (UINT32 *) buf; UINT32 intSize = allocSize / sizeof(UINT32); if (allocFlags & ALLOC_ZEROIZE) { memset(buf, 0, allocSize); } #ifdef CMS_MEM_POISON_ALLOC_FREE else { /* * Set alloc'ed buffer to garbage to catch use-before-init. * But we also allocate huge buffers for storing image downloads. * Don't bother writing garbage to those huge buffers. */ if (allocSize < 64 * 1024) { memset(buf, CMS_MEM_ALLOC_PATTERN, allocSize); } } #endif /* * Record the allocFlags in the first word, and the * size of user buffer in the next 2 words of the buffer. * Make 2 copies of the size in case one of the copies gets corrupted by * an underflow. Make one copy the XOR of the other so that there are * not so many 0's in size fields. */ intBuf[0] = allocFlags; intBuf[1] = size; intBuf[2] = intBuf[1] ^ 0xffffffff; buf = &(intBuf[3]); /* this gets returned to user */ #ifdef CMS_MEM_DEBUG { UINT8 *charBuf = (UINT8 *) buf; UINT32 i, roundup4Size = ROUNDUP4(size); for (i=size; i < roundup4Size; i++) { charBuf[i] = CMS_MEM_FOOTER_PATTERN & 0xff; } intBuf[intSize - 1] = CMS_MEM_FOOTER_PATTERN; intBuf[intSize - 2] = CMS_MEM_FOOTER_PATTERN; } #endif #ifdef CMS_MEM_LEAK_TRACING { AllocRecord *allocRec; if (!(allocRec = calloc(1, sizeof(AllocRecord)))) { cmsLog_error("could not malloc a record to track alloc"); } else { allocRec->bufAddr = buf; allocRec->userSize = size; allocRec->seq = allocSeq++; backtrace(allocRec->stackAddr, NUM_STACK_ENTRIES); /* * new allocs are placed at the beginning of the list, right after * the head. */ dlist_append((struct dlist_node *)allocRec, &glbAllocRec); } /* * do periodic garbage collection on the allocRecs which point * to shmBuf's that has been freed by another app. */ if ((allocSeq % 2000) == 0) { cmsLog_debug("Starting allocRec garbage collection"); garbageCollectAllocRec(); cmsLog_debug("garbage collection done"); } } #endif } return buf; }
void utlMem_free(void *buf) { UINT32 size; if (buf != NULL) { UINTPTR *intBuf = (UINTPTR *) (((UINTPTR) buf) - UTL_MEM_HEADER_LENGTH); #ifdef UTL_MEM_LEAK_TRACING { AllocRecord *allocRec; dlist_for_each_entry(allocRec, &glbAllocRec, dlist) if (allocRec->bufAddr == buf) break; if ((DlistNode *) allocRec != &glbAllocRec) { dlist_del((struct dlist_node *) allocRec); free(allocRec); } } #endif size = intBuf[1]; if (intBuf[1] != (intBuf[2] ^ UTL_MEM_HEADER_MASK)) { utlLog_error("memory underflow detected, %d %d", intBuf[1], intBuf[2]); utlAst_assert(0); return; } #ifdef UTL_MEM_DEBUG { UINT32 allocSize, intSize, roundupSize, i; UINT8 *charBuf = (UINT8 *) buf; allocSize = REAL_ALLOC_SIZE(intBuf[1]); intSize = allocSize / sizeof(UINTPTR); roundupSize = ROUNDUP(intBuf[1]); for (i=intBuf[1]; i < roundupSize; i++) { if (charBuf[i] != (UINT8) (UTL_MEM_FOOTER_PATTERN & 0xff)) { utlLog_error("memory overflow detected at idx=%d 0x%x 0x%x 0x%x", i, charBuf[i], intBuf[intSize-1], intBuf[intSize-2]); utlAst_assert(0); return; } } if ((intBuf[intSize - 1] != UTL_MEM_FOOTER_PATTERN) || (intBuf[intSize - 2] != UTL_MEM_FOOTER_PATTERN)) { utlLog_error("memory overflow detected, 0x%x 0x%x", intBuf[intSize - 1], intBuf[intSize - 2]); utlAst_assert(0); return; } #ifdef UTL_MEM_POISON_ALLOC_FREE /* * write garbage into buffer which is about to be freed to detect * users of freed buffers. */ memset(intBuf, UTL_MEM_FREE_PATTERN, allocSize); #endif } #endif /* UTL_MEM_DEBUG */ buf = intBuf; /* buf points to real start of buffer */ osl_free(buf); mStats.bytesAllocd -= size; mStats.numFrees++; }