static void *AcquireBlock(size_t size) { register size_t i; register void *block; /* Find free block. */ size=(size_t) (size+sizeof(size_t)+6*sizeof(size_t)-1) & -(4U*sizeof(size_t)); i=AllocationPolicy(size); block=memory_pool.blocks[i]; while ((block != (void *) NULL) && (SizeOfBlock(block) < size)) block=NextBlockInList(block); if (block == (void *) NULL) { i++; while (memory_pool.blocks[i] == (void *) NULL) i++; block=memory_pool.blocks[i]; if (i >= MaxBlocks) return((void *) NULL); } assert((*BlockHeader(NextBlock(block)) & PreviousBlockBit) == 0); assert(SizeOfBlock(block) >= size); RemoveFreeBlock(block,AllocationPolicy(SizeOfBlock(block))); if (SizeOfBlock(block) > size) { size_t blocksize; void *next; /* Split block. */ next=(char *) block+size; blocksize=SizeOfBlock(block)-size; *BlockHeader(next)=blocksize; *BlockFooter(next,blocksize)=blocksize; InsertFreeBlock(next,AllocationPolicy(blocksize)); *BlockHeader(block)=size | (*BlockHeader(block) & ~SizeMask); } assert(size == SizeOfBlock(block)); *BlockHeader(NextBlock(block))|=PreviousBlockBit; memory_pool.allocation+=size; return(block); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + E x p a n d H e a p % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ExpandHeap() get more memory from the system. It returns MagickTrue on % success otherwise MagickFalse. % % The format of the ExpandHeap method is: % % MagickBooleanType ExpandHeap(size_t size) % % A description of each parameter follows: % % o size: the size of the memory in bytes we require. % */ static MagickBooleanType ExpandHeap(size_t size) { DataSegmentInfo *segment_info; MagickBooleanType mapped; register ssize_t i; register void *block; size_t blocksize; void *segment; blocksize=((size+12*sizeof(size_t))+SegmentSize-1) & -SegmentSize; assert(memory_pool.number_segments < MaxSegments); segment=MapBlob(-1,IOMode,0,blocksize); mapped=segment != (void *) NULL ? MagickTrue : MagickFalse; if (segment == (void *) NULL) segment=(void *) memory_methods.acquire_memory_handler(blocksize); if (segment == (void *) NULL) return(MagickFalse); segment_info=(DataSegmentInfo *) free_segments; free_segments=segment_info->next; segment_info->mapped=mapped; segment_info->length=blocksize; segment_info->allocation=segment; segment_info->bound=(char *) segment+blocksize; i=(ssize_t) memory_pool.number_segments-1; for ( ; (i >= 0) && (memory_pool.segments[i]->allocation > segment); i--) memory_pool.segments[i+1]=memory_pool.segments[i]; memory_pool.segments[i+1]=segment_info; memory_pool.number_segments++; size=blocksize-12*sizeof(size_t); block=(char *) segment_info->allocation+4*sizeof(size_t); *BlockHeader(block)=size | PreviousBlockBit; *BlockFooter(block,size)=size; InsertFreeBlock(block,AllocationPolicy(size)); block=NextBlock(block); assert(block < segment_info->bound); *BlockHeader(block)=2*sizeof(size_t); *BlockHeader(NextBlock(block))=PreviousBlockBit; return(MagickTrue); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e l i n q u i s h M a g i c k M e m o r y % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % RelinquishMagickMemory() frees memory acquired with AcquireMagickMemory() % or AcquireQuantumMemory() for reuse. % % The format of the RelinquishMagickMemory method is: % % void *RelinquishMagickMemory(void *memory) % % A description of each parameter follows: % % o memory: A pointer to a block of memory to free for reuse. % */ MagickExport void *RelinquishMagickMemory(void *memory) { if (memory == (void *) NULL) return((void *) NULL); #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT) memory_methods.destroy_memory_handler(memory); #else LockSemaphoreInfo(memory_semaphore); assert((SizeOfBlock(memory) % (4*sizeof(size_t))) == 0); assert((*BlockHeader(NextBlock(memory)) & PreviousBlockBit) != 0); if ((*BlockHeader(memory) & PreviousBlockBit) == 0) { void *previous; /* Coalesce with previous adjacent block. */ previous=PreviousBlock(memory); RemoveFreeBlock(previous,AllocationPolicy(SizeOfBlock(previous))); *BlockHeader(previous)=(SizeOfBlock(previous)+SizeOfBlock(memory)) | (*BlockHeader(previous) & ~SizeMask); memory=previous; } if ((*BlockHeader(NextBlock(NextBlock(memory))) & PreviousBlockBit) == 0) { void *next; /* Coalesce with next adjacent block. */ next=NextBlock(memory); RemoveFreeBlock(next,AllocationPolicy(SizeOfBlock(next))); *BlockHeader(memory)=(SizeOfBlock(memory)+SizeOfBlock(next)) | (*BlockHeader(memory) & ~SizeMask); } *BlockFooter(memory,SizeOfBlock(memory))=SizeOfBlock(memory); *BlockHeader(NextBlock(memory))&=(~PreviousBlockBit); InsertFreeBlock(memory,AllocationPolicy(SizeOfBlock(memory))); UnlockSemaphoreInfo(memory_semaphore); #endif return((void *) NULL); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e l i n q u i s h M a g i c k M e m o r y % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % RelinquishMagickMemory() zeros memory that has been allocated, frees it for % reuse. % % The format of the RelinquishMagickMemory method is: % % void *RelinquishMagickMemory(void *memory) % % A description of each parameter follows: % % o memory: A pointer to a block of memory to free for reuse. % */ MagickExport void *RelinquishMagickMemory(void *memory) { if (memory == (void *) NULL) return((void *) NULL); #if !defined(UseEmbeddableMagick) free(memory); #else assert((SizeOfBlock(memory) % (4*sizeof(size_t))) == 0); assert((*BlockHeader(NextBlock(memory)) & PreviousBlockBit) != 0); AcquireSemaphoreInfo(&memory_semaphore); if ((*BlockHeader(memory) & PreviousBlockBit) == 0) { void *previous; /* Coalesce with previous adjacent block. */ previous=PreviousBlock(memory); RemoveFreeBlock(previous,AllocationPolicy(SizeOfBlock(previous))); *BlockHeader(previous)=(SizeOfBlock(previous)+SizeOfBlock(memory)) | (*BlockHeader(previous) & ~SizeMask); memory=previous; } if ((*BlockHeader(NextBlock(NextBlock(memory))) & PreviousBlockBit) == 0) { void *next; /* Coalesce with next adjacent block. */ next=NextBlock(memory); RemoveFreeBlock(next,AllocationPolicy(SizeOfBlock(next))); *BlockHeader(memory)=(SizeOfBlock(memory)+SizeOfBlock(next)) | (*BlockHeader(memory) & ~SizeMask); } *BlockFooter(memory,SizeOfBlock(memory))=SizeOfBlock(memory); *BlockHeader(NextBlock(memory))&=(~PreviousBlockBit); InsertFreeBlock(memory,AllocationPolicy(SizeOfBlock(memory))); RelinquishSemaphoreInfo(memory_semaphore); #endif return((void *) NULL); }
void xHeap::FreeMedium(void * p) { ASSERT("Trying to free NULL pointer" && p); ASSERT("Heap corrupted!" && mediumStats.allocCount > mediumStats.freeCount); #ifdef DEBUG_APP_HEAP p = (uint8*)p - sizeof(int); ASSERT("Heap corrupted!" && *(int*)p == DUMMY_MEDIUM_USED_ID_PRE); // *(int*)p = DUMMY_MEDIUM_FREE_ID_PRE; #endif Block * block = ((Block*)p) - 1; ASSERT("Double deallocation!" && !block->isFree); #ifdef DEBUG_APP_HEAP { ASSERT("Heap corrupted!" && *((int*)((uint8*)p + block->DataSize() + sizeof(int))) == DUMMY_MEDIUM_USED_ID_POST); // *check_p = DUMMY_MEDIUM_FREE_ID_POST; } #endif mediumStats.RegisterFree(block->size, block->DataSize()); Block * prev = block->prev; if(prev->isFree && prev->page == block->page) { ASSERT("Heap corrupted!" && ((uint8*)prev) + prev->size == (uint8*)block); prev->size += block->size; ((FreeBlock*)prev)->RemoveFreeLink(); block->RemoveLink(); block = prev; mediumStats.mergeCount++; } Block * next = block->next; if(next->isFree && next->page == block->page) { ASSERT("Heap corrupted!" && ((uint8*)block) + block->size == (uint8*)next); block->size += next->size; ((FreeBlock*)next)->RemoveFreeLink(); next->RemoveLink(); mediumStats.mergeCount++; } block->isFree = true; #ifdef DEBUG_APP_HEAP *(int*)(block+1) = DUMMY_MEDIUM_FREE_ID_PRE; *(int*)((uint8*)(block+1) + block->DataSize() + sizeof(int)) = DUMMY_MEDIUM_FREE_ID_POST; #endif InsertFreeBlock((FreeBlock*)block); #if defined(DEBUG_APP_HEAP) && defined(AEE_SIMULATOR) // CheckMemory(); #endif }
void * xHeap::AllocMedium(uint32 size, const char * filename, int line) { #else void * xHeap::AllocMedium(uint32 size) { #endif #ifdef DEBUG_APP_HEAP // static int step = 0; // step++; #endif uint32 saveSize = size; size = (size + ALIGN - 1 + sizeof(Block) + DUMMY_ID_SIZE) & ~(ALIGN - 1); Block * block = dummyFree.nextFree; if(block->size < size) // block == &dummyFree => dummyFree.size == 0 { if(size > pageSize / 2) { #ifdef DEBUG_APP_HEAP return AllocLarge(saveSize, filename, line); #else return AllocLarge(saveSize); #endif } block = (Block*)MALLOC(pageSize); if(!block) { return NULL; } #ifdef DEBUG_APP_HEAP block->filename = filename; block->line = line; #endif block->page = nextPage++; block->size = pageSize; block->isFree = true; block->InsertBefore(dummyBlock.next); ((FreeBlock*)block)->InsertBeforeFreeLink(dummyFree.nextFree); mediumStats.allocSize += block->size; } else { mediumStats.hitCount++; #ifdef FIND_BEST_FREE_BLOCK for(FreeBlock * next = ((FreeBlock*)block)->nextFree; next->size >= size; ) { block = next; next = ((FreeBlock*)block)->nextFree; } #endif } block->size -= size; if(block->size < MAX_SMALL_SIZE && (block->size < MAX_SMALL_SIZE/2 || block->next->page != block->page)) { #ifdef DEBUG_APP_HEAP block->filename = filename; block->line = line; #endif block->size += size; ((FreeBlock*)block)->RemoveFreeLink(); } else { #ifdef DEBUG_APP_HEAP *(int*)(block+1) = DUMMY_MEDIUM_FREE_ID_PRE; *(int*)((uint8*)(block+1) + block->DataSize() + sizeof(int)) = DUMMY_MEDIUM_FREE_ID_POST; #endif if(block->size < ((FreeBlock*)block)->nextFree->size) { ((FreeBlock*)block)->RemoveFreeLink(); InsertFreeBlock((FreeBlock*)block); } ASSERT("Heap corrupted!" && (block->size & 3) == 0); Block * newBlock = (Block*)(((uint8*)block) + block->size); #ifdef DEBUG_APP_HEAP newBlock->filename = filename; newBlock->line = line; #endif newBlock->page = block->page; newBlock->size = size; newBlock->InsertAfter(block); block = newBlock; } block->isFree = false; uint32 dataSize = block->DataSize(); mediumStats.RegisterAlloc(block->size, dataSize); uint8 * p = (uint8*)(block+1); p[-1] = BT_MEDIUM; #ifdef DEBUG_APP_HEAP *(int*)p = DUMMY_MEDIUM_USED_ID_PRE; p += sizeof(int); *(int*)(p + dataSize) = DUMMY_MEDIUM_USED_ID_POST; #endif MEMSET(p, 0, dataSize); #if defined(DEBUG_APP_HEAP) && defined(AEE_SIMULATOR) // CheckMemory(); #endif return p; }