/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % A c q u i r e V i r t u a l M e m o r y % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % AcquireVirtualMemory() allocates a pointer to a block of memory at least size % bytes suitably aligned for any use. % % The format of the AcquireVirtualMemory method is: % % MemoryInfo *AcquireVirtualMemory(const size_t count,const size_t quantum) % % A description of each parameter follows: % % o count: the number of quantum elements to allocate. % % o quantum: the number of bytes in each quantum. % */ MagickExport MemoryInfo *AcquireVirtualMemory(const size_t count, const size_t quantum) { MemoryInfo *memory_info; size_t length; length=count*quantum; if ((count == 0) || (quantum != (length/count))) { errno=ENOMEM; return((void *) NULL); } memory_info=(MemoryInfo *) MagickAssumeAligned(AcquireAlignedMemory(1, sizeof(*memory_info))); if (memory_info == (MemoryInfo *) NULL) ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); (void) ResetMagickMemory(memory_info,0,sizeof(*memory_info)); memory_info->length=length; memory_info->signature=MagickSignature; memory_info->blob=AcquireMagickMemory(length); if (memory_info->blob == NULL) { /* Heap memory failed, try anonymous memory mapping. */ memory_info->mapped=MagickTrue; memory_info->blob=MapBlob(-1,IOMode,0,length); } if (memory_info->blob == NULL) { int file; /* Anonymous memory mapping failed, try file-backed memory mapping. */ file=AcquireUniqueFileResource(memory_info->filename); file=open_utf8(memory_info->filename,O_RDWR | O_CREAT | O_BINARY | O_EXCL, S_MODE); if (file == -1) file=open_utf8(memory_info->filename,O_RDWR | O_BINARY,S_MODE); if (file != -1) { if ((lseek(file,length-1,SEEK_SET) >= 0) && (write(file,"",1) == 1)) memory_info->blob=MapBlob(file,IOMode,0,length); (void) close(file); } } if (memory_info->blob == NULL) return(RelinquishVirtualMemory(memory_info)); return(memory_info); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % + 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); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % A c q u i r e V i r t u a l M e m o r y % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % AcquireVirtualMemory() allocates a pointer to a block of memory at least size % bytes suitably aligned for any use. % % The format of the AcquireVirtualMemory method is: % % MemoryInfo *AcquireVirtualMemory(const size_t count,const size_t quantum) % % A description of each parameter follows: % % o count: the number of quantum elements to allocate. % % o quantum: the number of bytes in each quantum. % */ MagickExport MemoryInfo *AcquireVirtualMemory(const size_t count, const size_t quantum) { MemoryInfo *memory_info; size_t length; length=count*quantum; if ((count == 0) || (quantum != (length/count))) { errno=ENOMEM; return((MemoryInfo *) NULL); } memory_info=(MemoryInfo *) MagickAssumeAligned(AcquireAlignedMemory(1, sizeof(*memory_info))); if (memory_info == (MemoryInfo *) NULL) ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); (void) ResetMagickMemory(memory_info,0,sizeof(*memory_info)); memory_info->length=length; memory_info->signature=MagickSignature; if (AcquireMagickResource(MemoryResource,length) != MagickFalse) { memory_info->blob=AcquireAlignedMemory(1,length); if (memory_info->blob != NULL) memory_info->type=AlignedVirtualMemory; else RelinquishMagickResource(MemoryResource,length); } if ((memory_info->blob == NULL) && (AcquireMagickResource(MapResource,length) != MagickFalse)) { /* Heap memory failed, try anonymous memory mapping. */ memory_info->blob=MapBlob(-1,IOMode,0,length); if (memory_info->blob != NULL) memory_info->type=MapVirtualMemory; else RelinquishMagickResource(MapResource,length); } if (memory_info->blob == NULL) { int file; /* Anonymous memory mapping failed, try file-backed memory mapping. */ file=AcquireUniqueFileResource(memory_info->filename); if (file != -1) { if ((lseek(file,length-1,SEEK_SET) >= 0) && (write(file,"",1) == 1)) { memory_info->blob=MapBlob(file,IOMode,0,length); if (memory_info->blob != NULL) { memory_info->type=MapVirtualMemory; (void) AcquireMagickResource(MapResource,length); } } (void) close(file); } } if (memory_info->blob == NULL) { memory_info->blob=AcquireMagickMemory(length); if (memory_info->blob != NULL) memory_info->type=UnalignedVirtualMemory; } if (memory_info->blob == NULL) memory_info=RelinquishVirtualMemory(memory_info); return(memory_info); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % A c q u i r e V i r t u a l M e m o r y % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % AcquireVirtualMemory() allocates a pointer to a block of memory at least size % bytes suitably aligned for any use. % % The format of the AcquireVirtualMemory method is: % % MemoryInfo *AcquireVirtualMemory(const size_t count,const size_t quantum) % % A description of each parameter follows: % % o count: the number of quantum elements to allocate. % % o quantum: the number of bytes in each quantum. % */ MagickExport MemoryInfo *AcquireVirtualMemory(const size_t count, const size_t quantum) { MemoryInfo *memory_info; size_t extent; if (CheckMemoryOverflow(count,quantum) != MagickFalse) return((MemoryInfo *) NULL); memory_info=(MemoryInfo *) MagickAssumeAligned(AcquireAlignedMemory(1, sizeof(*memory_info))); if (memory_info == (MemoryInfo *) NULL) ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); (void) ResetMagickMemory(memory_info,0,sizeof(*memory_info)); extent=count*quantum; memory_info->length=extent; memory_info->signature=MagickCoreSignature; if (AcquireMagickResource(MemoryResource,extent) != MagickFalse) { memory_info->blob=AcquireAlignedMemory(1,extent); if (memory_info->blob != NULL) { memory_info->type=AlignedVirtualMemory; return(memory_info); } } RelinquishMagickResource(MemoryResource,extent); if (AcquireMagickResource(MapResource,extent) != MagickFalse) { /* Heap memory failed, try anonymous memory mapping. */ memory_info->blob=MapBlob(-1,IOMode,0,extent); if (memory_info->blob != NULL) { memory_info->type=MapVirtualMemory; return(memory_info); } if (AcquireMagickResource(DiskResource,extent) != MagickFalse) { int file; /* Anonymous memory mapping failed, try file-backed memory mapping. If the MapResource request failed, there is no point in trying file-backed memory mapping. */ file=AcquireUniqueFileResource(memory_info->filename); if (file != -1) { if ((lseek(file,extent-1,SEEK_SET) == (extent-1)) && (write(file,"",1) == 1)) { memory_info->blob=MapBlob(file,IOMode,0,extent); if (memory_info->blob != NULL) { (void) close(file); memory_info->type=MapVirtualMemory; return(memory_info); } } /* File-backed memory mapping failed, delete the temporary file. */ (void) close(file); (void) RelinquishUniqueFileResource(memory_info->filename); *memory_info->filename = '\0'; } } RelinquishMagickResource(DiskResource,extent); } RelinquishMagickResource(MapResource,extent); if (memory_info->blob == NULL) { memory_info->blob=AcquireMagickMemory(extent); if (memory_info->blob != NULL) memory_info->type=UnalignedVirtualMemory; } if (memory_info->blob == NULL) memory_info=RelinquishVirtualMemory(memory_info); return(memory_info); }