void setBackRef(BackRefIdx backRefIdx, void *newPtr) { MALLOC_ASSERT(backRefIdx.getMaster()<=backRefMaster->lastUsed && backRefIdx.getOffset()<BR_MAX_CNT, ASSERT_TEXT); *(void**)((uintptr_t)backRefMaster->backRefBl[backRefIdx.getMaster()] + sizeof(BackRefBlock) + backRefIdx.getOffset()*sizeof(void*)) = newPtr; }
void removeBackRef(BackRefIdx backRefIdx) { MALLOC_ASSERT(!backRefIdx.isInvalid(), ASSERT_TEXT); MALLOC_ASSERT(backRefIdx.getMaster()<=backRefMaster->lastUsed && backRefIdx.getOffset()<BR_MAX_CNT, ASSERT_TEXT); BackRefBlock *currBlock = backRefMaster->backRefBl[backRefIdx.getMaster()]; FreeObject *freeObj = (FreeObject*)((uintptr_t)currBlock + sizeof(BackRefBlock) + backRefIdx.getOffset()*sizeof(void*)); MALLOC_ASSERT(((uintptr_t)freeObj>(uintptr_t)currBlock && (uintptr_t)freeObj<(uintptr_t)currBlock + slabSize), ASSERT_TEXT); { MallocMutex::scoped_lock lock(currBlock->blockMutex); freeObj->next = currBlock->freeList; MALLOC_ASSERT(!freeObj->next || ((uintptr_t)freeObj->next > (uintptr_t)currBlock && (uintptr_t)freeObj->next < (uintptr_t)currBlock + slabSize), ASSERT_TEXT); currBlock->freeList = freeObj; currBlock->allocatedCount--; } // TODO: do we need double-check here? if (!currBlock->addedToForUse && currBlock!=backRefMaster->active) { MallocMutex::scoped_lock lock(masterMutex); if (!currBlock->addedToForUse && currBlock!=backRefMaster->active) backRefMaster->addToForUseList(currBlock); } }
LargeMemoryBlock *ExtMemoryPool::mallocLargeObject(size_t allocationSize) { #if __TBB_MALLOC_LOCACHE_STAT AtomicIncrement(mallocCalls); AtomicAdd(memAllocKB, allocationSize/1024); #endif LargeMemoryBlock* lmb = loc.get(allocationSize); if (!lmb) { BackRefIdx backRefIdx = BackRefIdx::newBackRef(/*largeObj=*/true); if (backRefIdx.isInvalid()) return NULL; // unalignedSize is set in getLargeBlock lmb = backend.getLargeBlock(allocationSize); if (!lmb) { removeBackRef(backRefIdx); loc.rollbackCacheState(allocationSize); return NULL; } lmb->backRefIdx = backRefIdx; STAT_increment(getThreadId(), ThreadCommonCounters, allocNewLargeObj); } else { #if __TBB_MALLOC_LOCACHE_STAT AtomicIncrement(cacheHits); AtomicAdd(memHitKB, allocationSize/1024); #endif } return lmb; }
void *ExtMemoryPool::mallocLargeObject(size_t size, size_t alignment) { size_t headersSize = sizeof(LargeMemoryBlock)+sizeof(LargeObjectHdr); // TODO: take into account that they are already largeObjectAlignment-aligned size_t allocationSize = alignUp(size+headersSize+alignment, largeBlockCacheStep); if (allocationSize < size) // allocationSize is wrapped around after alignUp return NULL; LargeMemoryBlock* lmb = loc.get(this, allocationSize); if (!lmb) { BackRefIdx backRefIdx = BackRefIdx::newBackRef(/*largeObj=*/true); if (backRefIdx.isInvalid()) return NULL; // unalignedSize is set in getLargeBlock lmb = backend.getLargeBlock(allocationSize); if (!lmb) { removeBackRef(backRefIdx); return NULL; } lmb->backRefIdx = backRefIdx; STAT_increment(getThreadId(), ThreadCommonCounters, allocNewLargeObj); } void *alignedArea = (void*)alignUp((uintptr_t)lmb+headersSize, alignment); LargeObjectHdr *header = (LargeObjectHdr*)alignedArea-1; header->memoryBlock = lmb; header->backRefIdx = lmb->backRefIdx; setBackRef(header->backRefIdx, header); lmb->objectSize = size; MALLOC_ASSERT( isLargeObject(alignedArea), ASSERT_TEXT ); return alignedArea; }