/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e l i n q u i s h V i r t u a l M e m o r y % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % RelinquishVirtualMemory() frees memory acquired with AcquireVirtualMemory(). % % The format of the RelinquishVirtualMemory method is: % % MemoryInfo *RelinquishVirtualMemory(MemoryInfo *memory_info) % % A description of each parameter follows: % % o memory_info: A pointer to a block of memory to free for reuse. % */ MagickExport MemoryInfo *RelinquishVirtualMemory(MemoryInfo *memory_info) { assert(memory_info != (MemoryInfo *) NULL); assert(memory_info->signature == MagickSignature); if (memory_info->blob != (void *) NULL) switch (memory_info->type) { case AlignedVirtualMemory: { memory_info->blob=RelinquishAlignedMemory(memory_info->blob); RelinquishMagickResource(MemoryResource,memory_info->length); break; } case MapVirtualMemory: { (void) UnmapBlob(memory_info->blob,memory_info->length); memory_info->blob=NULL; RelinquishMagickResource(MapResource,memory_info->length); if (*memory_info->filename != '\0') (void) RelinquishUniqueFileResource(memory_info->filename); break; } case UnalignedVirtualMemory: default: { memory_info->blob=RelinquishMagickMemory(memory_info->blob); break; } } memory_info->signature=(~MagickSignature); memory_info=(MemoryInfo *) RelinquishAlignedMemory(memory_info); return(memory_info); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e l i n q u i s h U n i q u e F i l e R e s o u r c e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % RelinquishUniqueFileResource() relinquishes a unique file resource. % % The format of the RelinquishUniqueFileResource() method is: % % MagickBooleanType RelinquishUniqueFileResource(const char *path) % % A description of each parameter follows: % % o name: the name of the temporary resource. % % */ MagickExport MagickBooleanType RelinquishUniqueFileResource(const char *path) { char cache_path[MaxTextExtent]; assert(path != (const char *) NULL); (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path); if (temporary_resources != (SplayTreeInfo *) NULL) { register char *p; ResetSplayTreeIterator(temporary_resources); p=(char *) GetNextKeyInSplayTree(temporary_resources); while (p != (char *) NULL) { if (LocaleCompare(p,path) == 0) break; p=(char *) GetNextKeyInSplayTree(temporary_resources); } if (p != (char *) NULL) { (void) RemoveNodeFromSplayTree(temporary_resources,p); RelinquishMagickResource(FileResource,1); } } (void) CopyMagickString(cache_path,path,MaxTextExtent); AppendImageFormat("cache",cache_path); (void) remove(cache_path); return(remove(path) == 0 ? MagickTrue : MagickFalse); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % 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); }