bool TestReallocMsize(size_t startSz) { bool passed = true; char *buf = (char*)scalable_malloc(startSz); ASSERT(buf, ""); size_t realSz = scalable_msize(buf); ASSERT(realSz>=startSz, "scalable_msize must be not less then allocated size"); memset(buf, 'a', realSz-1); buf[realSz-1] = 0; char *buf1 = (char*)scalable_realloc(buf, 2*realSz); ASSERT(buf1, ""); ASSERT(scalable_msize(buf1)>=2*realSz, "scalable_msize must be not less then allocated size"); buf1[2*realSz-1] = 0; if ( strspn(buf1, "a") < realSz-1 ) { REPORT( "Error: data broken for %d Bytes object.\n", startSz); passed = false; } scalable_free(buf1); return passed; }
void FMallocTBB::Free( void* Ptr ) { if( !Ptr ) { return; } MEM_TIME(MemTime -= FPlatformTime::Seconds()) #if UE_BUILD_DEBUG || UE_BUILD_DEVELOPMENT FMemory::Memset(Ptr, DEBUG_FILL_FREED, scalable_msize(Ptr)); #endif IncrementTotalFreeCalls(); scalable_free(Ptr); MEM_TIME(MemTime += FPlatformTime::Seconds()) }
// regression test against incorrect work of msize/realloc // for aligned objects void TestAlignedMsize() { const int NUM = 4; char *p[NUM]; size_t objSizes[NUM]; size_t allocSz[] = {4, 8, 512, 2*1024, 4*1024, 8*1024, 16*1024, 0}; size_t align[] = {8, 512, 2*1024, 4*1024, 8*1024, 16*1024, 0}; for (int a=0; align[a]; a++) for (int s=0; allocSz[s]; s++) { for (int i=0; i<NUM; i++) { p[i] = (char*)scalable_aligned_malloc(allocSz[s], align[a]); ASSERT(is_aligned(p[i], align[a]), NULL); } for (int i=0; i<NUM; i++) { objSizes[i] = scalable_msize(p[i]); ASSERT(objSizes[i] >= allocSz[s], "allocated size must be not less than requested"); memset(p[i], i, objSizes[i]); } for (int i=0; i<NUM; i++) { for (unsigned j=0; j<objSizes[i]; j++) ASSERT(((char*)p[i])[j] == i, "Error: data broken"); } for (int i=0; i<NUM; i++) { p[i] = (char*)scalable_aligned_realloc(p[i], 2*allocSz[s], align[a]); ASSERT(is_aligned(p[i], align[a]), NULL); memset((char*)p[i]+allocSz[s], i+1, allocSz[s]); } for (int i=0; i<NUM; i++) { for (unsigned j=0; j<allocSz[s]; j++) ASSERT(((char*)p[i])[j] == i, "Error: data broken"); for (size_t j=allocSz[s]; j<2*allocSz[s]; j++) ASSERT(((char*)p[i])[j] == i+1, "Error: data broken"); } for (int i=0; i<NUM; i++) scalable_free(p[i]); } }
void* FMallocTBB::Realloc( void* Ptr, SIZE_T NewSize, uint32 Alignment ) { IncrementTotalReallocCalls(); MEM_TIME(MemTime -= FPlatformTime::Seconds()) #if UE_BUILD_DEBUG || UE_BUILD_DEVELOPMENT SIZE_T OldSize = 0; if (Ptr) { OldSize = scalable_msize(Ptr); if (NewSize < OldSize) { FMemory::Memset((uint8*)Ptr + NewSize, DEBUG_FILL_FREED, OldSize - NewSize); } } #endif void* NewPtr = NULL; if (Alignment != DEFAULT_ALIGNMENT) { Alignment = FMath::Max(NewSize >= 16 ? (uint32)16 : (uint32)8, Alignment); NewPtr = scalable_aligned_realloc(Ptr, NewSize, Alignment); } else { NewPtr = scalable_realloc(Ptr, NewSize); } #if UE_BUILD_DEBUG || UE_BUILD_DEVELOPMENT if (NewPtr && NewSize > OldSize ) { FMemory::Memset((uint8*)NewPtr + OldSize, DEBUG_FILL_NEW, NewSize - OldSize); } #endif if( !NewPtr && NewSize ) { OutOfMemory(NewSize, Alignment); } MEM_TIME(MemTime += FPlatformTime::Seconds()) return NewPtr; }
void TestObjectRecognition() { size_t headersSize = sizeof(LargeMemoryBlock)+sizeof(LargeObjectHdr); unsigned falseObjectSize = 113; // unsigned is the type expected by getObjectSize size_t obtainedSize; ASSERT(sizeof(BackRefIdx)==4, "Unexpected size of BackRefIdx"); ASSERT(getObjectSize(falseObjectSize)!=falseObjectSize, "Error in test: bad choice for false object size"); void* mem = scalable_malloc(2*slabSize); ASSERT(mem, "Memory was not allocated"); Block* falseBlock = (Block*)alignUp((uintptr_t)mem, slabSize); falseBlock->objectSize = falseObjectSize; char* falseSO = (char*)falseBlock + falseObjectSize*7; ASSERT(alignDown(falseSO, slabSize)==(void*)falseBlock, "Error in test: false object offset is too big"); void* bufferLOH = scalable_malloc(2*slabSize + headersSize); ASSERT(bufferLOH, "Memory was not allocated"); LargeObjectHdr* falseLO = (LargeObjectHdr*)alignUp((uintptr_t)bufferLOH + headersSize, slabSize); LargeObjectHdr* headerLO = (LargeObjectHdr*)falseLO-1; headerLO->memoryBlock = (LargeMemoryBlock*)bufferLOH; headerLO->memoryBlock->unalignedSize = 2*slabSize + headersSize; headerLO->memoryBlock->objectSize = slabSize + headersSize; headerLO->backRefIdx = BackRefIdx::newBackRef(/*largeObj=*/true); setBackRef(headerLO->backRefIdx, headerLO); ASSERT(scalable_msize(falseLO) == slabSize + headersSize, "Error in test: LOH falsification failed"); removeBackRef(headerLO->backRefIdx); const int NUM_OF_IDX = BR_MAX_CNT+2; BackRefIdx idxs[NUM_OF_IDX]; for (int cnt=0; cnt<2; cnt++) { for (int master = -10; master<10; master++) { falseBlock->backRefIdx.master = (uint16_t)master; headerLO->backRefIdx.master = (uint16_t)master; for (int bl = -10; bl<BR_MAX_CNT+10; bl++) { falseBlock->backRefIdx.offset = (uint16_t)bl; headerLO->backRefIdx.offset = (uint16_t)bl; for (int largeObj = 0; largeObj<2; largeObj++) { falseBlock->backRefIdx.largeObj = largeObj; headerLO->backRefIdx.largeObj = largeObj; obtainedSize = safer_scalable_msize(falseSO, NULL); ASSERT(obtainedSize==0, "Incorrect pointer accepted"); obtainedSize = safer_scalable_msize(falseLO, NULL); ASSERT(obtainedSize==0, "Incorrect pointer accepted"); } } } if (cnt == 1) { for (int i=0; i<NUM_OF_IDX; i++) removeBackRef(idxs[i]); break; } for (int i=0; i<NUM_OF_IDX; i++) { idxs[i] = BackRefIdx::newBackRef(/*largeObj=*/false); setBackRef(idxs[i], NULL); } } char *smallPtr = (char*)scalable_malloc(falseObjectSize); obtainedSize = safer_scalable_msize(smallPtr, NULL); ASSERT(obtainedSize==getObjectSize(falseObjectSize), "Correct pointer not accepted?"); scalable_free(smallPtr); obtainedSize = safer_scalable_msize(mem, NULL); ASSERT(obtainedSize>=2*slabSize, "Correct pointer not accepted?"); scalable_free(mem); scalable_free(bufferLOH); }
bool FMallocTBB::GetAllocationSize(void *Original, SIZE_T &SizeOut) { SizeOut = scalable_msize(Original); return true; }