2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6 % M M EEEEE M M OOO RRRR Y Y %
7 % MM MM E MM MM O O R R Y Y %
8 % M M M EEE M M M O O RRRR Y %
9 % M M E M M O O R R Y %
10 % M M EEEEE M M OOO R R Y %
13 % MagickCore Memory Allocation Methods %
20 % Copyright 1999-2018 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % https://www.imagemagick.org/script/license.php %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36 % Segregate our memory requirements from any program that calls our API. This
37 % should help reduce the risk of others changing our program state or causing
40 % Our custom memory allocation manager implements a best-fit allocation policy
41 % using segregated free lists. It uses a linear distribution of size classes
42 % for lower sizes and a power of two distribution of size classes at higher
43 % sizes. It is based on the paper, "Fast Memory Allocation using Lazy Fits."
44 % written by Yoo C. Chung.
46 % By default, ANSI memory methods are called (e.g. malloc). Use the
47 % custom memory allocator by defining MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT
48 % to allocate memory with private anonymous mapping rather than from the
56 #include "MagickCore/studio.h"
57 #include "MagickCore/blob.h"
58 #include "MagickCore/blob-private.h"
59 #include "MagickCore/exception.h"
60 #include "MagickCore/exception-private.h"
61 #include "MagickCore/memory_.h"
62 #include "MagickCore/memory-private.h"
63 #include "MagickCore/policy.h"
64 #include "MagickCore/resource_.h"
65 #include "MagickCore/semaphore.h"
66 #include "MagickCore/string_.h"
67 #include "MagickCore/string-private.h"
68 #include "MagickCore/utility-private.h"
73 #define BlockFooter(block,size) \
74 ((size_t *) ((char *) (block)+(size)-2*sizeof(size_t)))
75 #define BlockHeader(block) ((size_t *) (block)-1)
76 #define BlockSize 4096
77 #define BlockThreshold 1024
78 #define MaxBlockExponent 16
79 #define MaxBlocks ((BlockThreshold/(4*sizeof(size_t)))+MaxBlockExponent+1)
80 #define MaxSegments 1024
81 #define MemoryGuard ((0xdeadbeef << 31)+0xdeafdeed)
82 #define NextBlock(block) ((char *) (block)+SizeOfBlock(block))
83 #define NextBlockInList(block) (*(void **) (block))
84 #define PreviousBlock(block) ((char *) (block)-(*((size_t *) (block)-2)))
85 #define PreviousBlockBit 0x01
86 #define PreviousBlockInList(block) (*((void **) (block)+1))
87 #define SegmentSize (2*1024*1024)
88 #define SizeMask (~0x01)
89 #define SizeOfBlock(block) (*BlockHeader(block) & SizeMask)
96 UndefinedVirtualMemory,
99 UnalignedVirtualMemory
102 typedef struct _DataSegmentInfo
114 struct _DataSegmentInfo
119 typedef struct _MagickMemoryMethods
122 acquire_memory_handler;
125 resize_memory_handler;
128 destroy_memory_handler;
129 } MagickMemoryMethods;
134 filename[MagickPathExtent];
149 typedef struct _MemoryPool
155 *blocks[MaxBlocks+1];
161 *segments[MaxSegments],
162 segment_pool[MaxSegments];
169 max_memory_request = 0,
170 virtual_anonymous_memory = 0;
173 static void* MSCMalloc(size_t size)
177 static void* MSCRealloc(void* ptr, size_t size)
179 return realloc(ptr, size);
181 static void MSCFree(void* ptr)
187 static MagickMemoryMethods
191 (AcquireMemoryHandler) MSCMalloc,
192 (ResizeMemoryHandler) MSCRealloc,
193 (DestroyMemoryHandler) MSCFree
195 (AcquireMemoryHandler) malloc,
196 (ResizeMemoryHandler) realloc,
197 (DestroyMemoryHandler) free
200 #if defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
205 *memory_semaphore = (SemaphoreInfo *) NULL;
207 static volatile DataSegmentInfo
208 *free_segments = (DataSegmentInfo *) NULL;
211 Forward declarations.
213 static MagickBooleanType
218 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
222 % A c q u i r e A l i g n e d M e m o r y %
226 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
228 % AcquireAlignedMemory() returns a pointer to a block of memory at least size
229 % bytes whose address is aligned on a cache line or page boundary.
231 % The format of the AcquireAlignedMemory method is:
233 % void *AcquireAlignedMemory(const size_t count,const size_t quantum)
235 % A description of each parameter follows:
237 % o count: the number of quantum elements to allocate.
239 % o quantum: the number of bytes in each quantum.
242 MagickExport void *AcquireAlignedMemory(const size_t count,const size_t quantum)
244 #define AlignedExtent(size,alignment) \
245 (((size)+((alignment)-1)) & ~((alignment)-1))
255 if (HeapOverflowSanityCheck(count,quantum) != MagickFalse)
256 return((void *) NULL);
259 alignment=CACHE_LINE_SIZE;
260 if (size > (size_t) (GetMagickPageSize() >> 1))
261 alignment=(size_t) GetMagickPageSize();
262 extent=AlignedExtent(size,CACHE_LINE_SIZE);
263 if ((size == 0) || (extent < size))
264 return((void *) NULL);
265 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
266 if (posix_memalign(&memory,alignment,extent) != 0)
268 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
269 memory=_aligned_malloc(extent,alignment);
275 extent=(size+alignment-1)+sizeof(void *);
281 memory=(void *) AlignedExtent((size_t) p+sizeof(void *),alignment);
282 *((void **) memory-1)=p;
290 #if defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
292 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
296 + A c q u i r e B l o c k %
300 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
302 % AcquireBlock() returns a pointer to a block of memory at least size bytes
303 % suitably aligned for any use.
305 % The format of the AcquireBlock method is:
307 % void *AcquireBlock(const size_t size)
309 % A description of each parameter follows:
311 % o size: the size of the memory in bytes to allocate.
315 static inline size_t AllocationPolicy(size_t size)
321 The linear distribution.
324 assert(size % (4*sizeof(size_t)) == 0);
325 if (size <= BlockThreshold)
326 return(size/(4*sizeof(size_t)));
328 Check for the largest block size.
330 if (size > (size_t) (BlockThreshold*(1L << (MaxBlockExponent-1L))))
331 return(MaxBlocks-1L);
333 Otherwise use a power of two distribution.
335 blocksize=BlockThreshold/(4*sizeof(size_t));
336 for ( ; size > BlockThreshold; size/=2)
338 assert(blocksize > (BlockThreshold/(4*sizeof(size_t))));
339 assert(blocksize < (MaxBlocks-1L));
343 static inline void InsertFreeBlock(void *block,const size_t i)
352 size=SizeOfBlock(block);
353 previous=(void *) NULL;
354 next=memory_pool.blocks[i];
355 while ((next != (void *) NULL) && (SizeOfBlock(next) < size))
358 next=NextBlockInList(next);
360 PreviousBlockInList(block)=previous;
361 NextBlockInList(block)=next;
362 if (previous != (void *) NULL)
363 NextBlockInList(previous)=block;
365 memory_pool.blocks[i]=block;
366 if (next != (void *) NULL)
367 PreviousBlockInList(next)=block;
370 static inline void RemoveFreeBlock(void *block,const size_t i)
376 next=NextBlockInList(block);
377 previous=PreviousBlockInList(block);
378 if (previous == (void *) NULL)
379 memory_pool.blocks[i]=next;
381 NextBlockInList(previous)=next;
382 if (next != (void *) NULL)
383 PreviousBlockInList(next)=previous;
386 static void *AcquireBlock(size_t size)
397 size=(size_t) (size+sizeof(size_t)+6*sizeof(size_t)-1) & -(4U*sizeof(size_t));
398 i=AllocationPolicy(size);
399 block=memory_pool.blocks[i];
400 while ((block != (void *) NULL) && (SizeOfBlock(block) < size))
401 block=NextBlockInList(block);
402 if (block == (void *) NULL)
405 while (memory_pool.blocks[i] == (void *) NULL)
407 block=memory_pool.blocks[i];
409 return((void *) NULL);
411 assert((*BlockHeader(NextBlock(block)) & PreviousBlockBit) == 0);
412 assert(SizeOfBlock(block) >= size);
413 RemoveFreeBlock(block,AllocationPolicy(SizeOfBlock(block)));
414 if (SizeOfBlock(block) > size)
425 next=(char *) block+size;
426 blocksize=SizeOfBlock(block)-size;
427 *BlockHeader(next)=blocksize;
428 *BlockFooter(next,blocksize)=blocksize;
429 InsertFreeBlock(next,AllocationPolicy(blocksize));
430 *BlockHeader(block)=size | (*BlockHeader(block) & ~SizeMask);
432 assert(size == SizeOfBlock(block));
433 *BlockHeader(NextBlock(block))|=PreviousBlockBit;
434 memory_pool.allocation+=size;
440 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
444 % A c q u i r e M a g i c k M e m o r y %
448 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
450 % AcquireMagickMemory() returns a pointer to a block of memory at least size
451 % bytes suitably aligned for any use.
453 % The format of the AcquireMagickMemory method is:
455 % void *AcquireMagickMemory(const size_t size)
457 % A description of each parameter follows:
459 % o size: the size of the memory in bytes to allocate.
462 MagickExport void *AcquireMagickMemory(const size_t size)
467 #if !defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
468 memory=memory_methods.acquire_memory_handler(size == 0 ? 1UL : size);
470 if (memory_semaphore == (SemaphoreInfo *) NULL)
471 ActivateSemaphoreInfo(&memory_semaphore);
472 if (free_segments == (DataSegmentInfo *) NULL)
474 LockSemaphoreInfo(memory_semaphore);
475 if (free_segments == (DataSegmentInfo *) NULL)
480 assert(2*sizeof(size_t) > (size_t) (~SizeMask));
481 (void) memset(&memory_pool,0,sizeof(memory_pool));
482 memory_pool.allocation=SegmentSize;
483 memory_pool.blocks[MaxBlocks]=(void *) (-1);
484 for (i=0; i < MaxSegments; i++)
487 memory_pool.segment_pool[i].previous=
488 (&memory_pool.segment_pool[i-1]);
489 if (i != (MaxSegments-1))
490 memory_pool.segment_pool[i].next=(&memory_pool.segment_pool[i+1]);
492 free_segments=(&memory_pool.segment_pool[0]);
494 UnlockSemaphoreInfo(memory_semaphore);
496 LockSemaphoreInfo(memory_semaphore);
497 memory=AcquireBlock(size == 0 ? 1UL : size);
498 if (memory == (void *) NULL)
500 if (ExpandHeap(size == 0 ? 1UL : size) != MagickFalse)
501 memory=AcquireBlock(size == 0 ? 1UL : size);
503 UnlockSemaphoreInfo(memory_semaphore);
509 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
513 % A c q u i r e Q u a n t u m M e m o r y %
517 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
519 % AcquireQuantumMemory() returns a pointer to a block of memory at least
520 % count * quantum bytes suitably aligned for any use.
522 % The format of the AcquireQuantumMemory method is:
524 % void *AcquireQuantumMemory(const size_t count,const size_t quantum)
526 % A description of each parameter follows:
528 % o count: the number of quantum elements to allocate.
530 % o quantum: the number of bytes in each quantum.
533 MagickExport void *AcquireQuantumMemory(const size_t count,const size_t quantum)
538 if (HeapOverflowSanityCheck(count,quantum) != MagickFalse)
539 return((void *) NULL);
540 extent=count*quantum;
541 return(AcquireMagickMemory(extent));
545 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
549 % A c q u i r e V i r t u a l M e m o r y %
553 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
555 % AcquireVirtualMemory() allocates a pointer to a block of memory at least
556 % size bytes suitably aligned for any use. In addition to heap, it also
557 % supports memory-mapped and file-based memory-mapped memory requests.
559 % The format of the AcquireVirtualMemory method is:
561 % MemoryInfo *AcquireVirtualMemory(const size_t count,const size_t quantum)
563 % A description of each parameter follows:
565 % o count: the number of quantum elements to allocate.
567 % o quantum: the number of bytes in each quantum.
571 MagickExport MemoryInfo *AcquireVirtualMemory(const size_t count,
572 const size_t quantum)
583 if (HeapOverflowSanityCheck(count,quantum) != MagickFalse)
584 return((MemoryInfo *) NULL);
585 if (virtual_anonymous_memory == 0)
587 virtual_anonymous_memory=1;
588 value=GetPolicyValue("system:memory-map");
589 if (LocaleCompare(value,"anonymous") == 0)
592 The security policy sets anonymous mapping for the memory request.
594 #if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
595 virtual_anonymous_memory=2;
598 value=DestroyString(value);
600 memory_info=(MemoryInfo *) MagickAssumeAligned(AcquireAlignedMemory(1,
601 sizeof(*memory_info)));
602 if (memory_info == (MemoryInfo *) NULL)
603 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
604 (void) memset(memory_info,0,sizeof(*memory_info));
605 extent=count*quantum;
606 memory_info->length=extent;
607 memory_info->signature=MagickCoreSignature;
608 if ((virtual_anonymous_memory == 1) &&
609 ((count*quantum) <= GetMaxMemoryRequest()))
611 memory_info->blob=AcquireAlignedMemory(1,extent);
612 if (memory_info->blob != NULL)
613 memory_info->type=AlignedVirtualMemory;
615 if (memory_info->blob == NULL)
618 Acquire anonymous memory map.
620 memory_info->blob=NULL;
621 if ((count*quantum) <= GetMaxMemoryRequest())
622 memory_info->blob=MapBlob(-1,IOMode,0,extent);
623 if (memory_info->blob != NULL)
624 memory_info->type=MapVirtualMemory;
631 Anonymous memory mapping failed, try file-backed memory mapping.
633 file=AcquireUniqueFileResource(memory_info->filename);
639 offset=(MagickOffsetType) lseek(file,extent-1,SEEK_SET);
640 if ((offset == (MagickOffsetType) (extent-1)) &&
641 (write(file,"",1) == 1))
643 memory_info->blob=MapBlob(file,IOMode,0,extent);
644 if (memory_info->blob != NULL)
645 memory_info->type=MapVirtualMemory;
648 (void) RelinquishUniqueFileResource(
649 memory_info->filename);
650 *memory_info->filename='\0';
657 if (memory_info->blob == NULL)
659 memory_info->blob=AcquireQuantumMemory(1,extent);
660 if (memory_info->blob != NULL)
661 memory_info->type=UnalignedVirtualMemory;
663 if (memory_info->blob == NULL)
664 memory_info=RelinquishVirtualMemory(memory_info);
669 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
673 % C o p y M a g i c k M e m o r y %
677 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
679 % CopyMagickMemory() copies size bytes from memory area source to the
680 % destination. Copying between objects that overlap will take place
681 % correctly. It returns destination.
683 % The format of the CopyMagickMemory method is:
685 % void *CopyMagickMemory(void *destination,const void *source,
688 % A description of each parameter follows:
690 % o destination: the destination.
692 % o source: the source.
694 % o size: the size of the memory in bytes to allocate.
697 MagickExport void *CopyMagickMemory(void *destination,const void *source,
700 register const unsigned char
703 register unsigned char
706 assert(destination != (void *) NULL);
707 assert(source != (const void *) NULL);
708 p=(const unsigned char *) source;
709 q=(unsigned char *) destination;
710 if (((q+size) < p) || (q > (p+size)))
713 default: return(memcpy(destination,source,size));
722 case 0: return(destination);
724 return(memmove(destination,source,size));
728 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
732 + D e s t r o y M a g i c k M e m o r y %
736 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
738 % DestroyMagickMemory() deallocates memory associated with the memory manager.
740 % The format of the DestroyMagickMemory method is:
742 % DestroyMagickMemory(void)
745 MagickExport void DestroyMagickMemory(void)
747 #if defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
751 if (memory_semaphore == (SemaphoreInfo *) NULL)
752 ActivateSemaphoreInfo(&memory_semaphore);
753 LockSemaphoreInfo(memory_semaphore);
754 for (i=0; i < (ssize_t) memory_pool.number_segments; i++)
755 if (memory_pool.segments[i]->mapped == MagickFalse)
756 memory_methods.destroy_memory_handler(
757 memory_pool.segments[i]->allocation);
759 (void) UnmapBlob(memory_pool.segments[i]->allocation,
760 memory_pool.segments[i]->length);
761 free_segments=(DataSegmentInfo *) NULL;
762 (void) memset(&memory_pool,0,sizeof(memory_pool));
763 UnlockSemaphoreInfo(memory_semaphore);
764 RelinquishSemaphoreInfo(&memory_semaphore);
768 #if defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
770 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
774 + E x p a n d H e a p %
778 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
780 % ExpandHeap() get more memory from the system. It returns MagickTrue on
781 % success otherwise MagickFalse.
783 % The format of the ExpandHeap method is:
785 % MagickBooleanType ExpandHeap(size_t size)
787 % A description of each parameter follows:
789 % o size: the size of the memory in bytes we require.
792 static MagickBooleanType ExpandHeap(size_t size)
812 blocksize=((size+12*sizeof(size_t))+SegmentSize-1) & -SegmentSize;
813 assert(memory_pool.number_segments < MaxSegments);
814 segment=MapBlob(-1,IOMode,0,blocksize);
815 mapped=segment != (void *) NULL ? MagickTrue : MagickFalse;
816 if (segment == (void *) NULL)
817 segment=(void *) memory_methods.acquire_memory_handler(blocksize);
818 if (segment == (void *) NULL)
820 segment_info=(DataSegmentInfo *) free_segments;
821 free_segments=segment_info->next;
822 segment_info->mapped=mapped;
823 segment_info->length=blocksize;
824 segment_info->allocation=segment;
825 segment_info->bound=(char *) segment+blocksize;
826 i=(ssize_t) memory_pool.number_segments-1;
827 for ( ; (i >= 0) && (memory_pool.segments[i]->allocation > segment); i--)
828 memory_pool.segments[i+1]=memory_pool.segments[i];
829 memory_pool.segments[i+1]=segment_info;
830 memory_pool.number_segments++;
831 size=blocksize-12*sizeof(size_t);
832 block=(char *) segment_info->allocation+4*sizeof(size_t);
833 *BlockHeader(block)=size | PreviousBlockBit;
834 *BlockFooter(block,size)=size;
835 InsertFreeBlock(block,AllocationPolicy(size));
836 block=NextBlock(block);
837 assert(block < segment_info->bound);
838 *BlockHeader(block)=2*sizeof(size_t);
839 *BlockHeader(NextBlock(block))=PreviousBlockBit;
845 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
849 % G e t M a g i c k M e m o r y M e t h o d s %
853 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
855 % GetMagickMemoryMethods() gets the methods to acquire, resize, and destroy
858 % The format of the GetMagickMemoryMethods() method is:
860 % void GetMagickMemoryMethods(AcquireMemoryHandler *acquire_memory_handler,
861 % ResizeMemoryHandler *resize_memory_handler,
862 % DestroyMemoryHandler *destroy_memory_handler)
864 % A description of each parameter follows:
866 % o acquire_memory_handler: method to acquire memory (e.g. malloc).
868 % o resize_memory_handler: method to resize memory (e.g. realloc).
870 % o destroy_memory_handler: method to destroy memory (e.g. free).
873 MagickExport void GetMagickMemoryMethods(
874 AcquireMemoryHandler *acquire_memory_handler,
875 ResizeMemoryHandler *resize_memory_handler,
876 DestroyMemoryHandler *destroy_memory_handler)
878 assert(acquire_memory_handler != (AcquireMemoryHandler *) NULL);
879 assert(resize_memory_handler != (ResizeMemoryHandler *) NULL);
880 assert(destroy_memory_handler != (DestroyMemoryHandler *) NULL);
881 *acquire_memory_handler=memory_methods.acquire_memory_handler;
882 *resize_memory_handler=memory_methods.resize_memory_handler;
883 *destroy_memory_handler=memory_methods.destroy_memory_handler;
887 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
891 + G e t M a x M e m o r y R e q u e s t %
895 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
897 % GetMaxMemoryRequest() returns the max_memory_request value.
899 % The format of the GetMaxMemoryRequest method is:
901 % size_t GetMaxMemoryRequest(void)
904 MagickExport size_t GetMaxMemoryRequest(void)
906 if (max_memory_request == 0)
911 max_memory_request=(size_t) MagickULLConstant(~0);
912 value=GetPolicyValue("system:max-memory-request");
913 if (value != (char *) NULL)
916 The security policy sets a max memory request limit.
918 max_memory_request=StringToSizeType(value,100.0);
919 value=DestroyString(value);
922 return(max_memory_request);
926 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
930 % G e t V i r t u a l M e m o r y B l o b %
934 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
936 % GetVirtualMemoryBlob() returns the virtual memory blob associated with the
937 % specified MemoryInfo structure.
939 % The format of the GetVirtualMemoryBlob method is:
941 % void *GetVirtualMemoryBlob(const MemoryInfo *memory_info)
943 % A description of each parameter follows:
945 % o memory_info: The MemoryInfo structure.
947 MagickExport void *GetVirtualMemoryBlob(const MemoryInfo *memory_info)
949 assert(memory_info != (const MemoryInfo *) NULL);
950 assert(memory_info->signature == MagickCoreSignature);
951 return(memory_info->blob);
955 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
959 + H e a p O v e r f l o w S a n i t y C h e c k %
963 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
965 % HeapOverflowSanityCheck() returns MagickTrue if the heap allocation request
966 % does not exceed the maximum limits of a size_t otherwise MagickFalse.
968 % The format of the HeapOverflowSanityCheck method is:
970 % MagickBooleanType HeapOverflowSanityCheck(const size_t count,
971 % const size_t quantum)
973 % A description of each parameter follows:
975 % o size: the size of the memory in bytes we require.
978 MagickExport MagickBooleanType HeapOverflowSanityCheck(const size_t count,
979 const size_t quantum)
985 if ((count == 0) || (quantum != (size/count)))
994 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
998 % R e l i n q u i s h A l i g n e d M e m o r y %
1002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1004 % RelinquishAlignedMemory() frees memory acquired with AcquireAlignedMemory()
1007 % The format of the RelinquishAlignedMemory method is:
1009 % void *RelinquishAlignedMemory(void *memory)
1011 % A description of each parameter follows:
1013 % o memory: A pointer to a block of memory to free for reuse.
1016 MagickExport void *RelinquishAlignedMemory(void *memory)
1018 if (memory == (void *) NULL)
1019 return((void *) NULL);
1020 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
1022 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
1023 _aligned_free(memory);
1025 free(*((void **) memory-1));
1031 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1035 % R e l i n q u i s h M a g i c k M e m o r y %
1039 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1041 % RelinquishMagickMemory() frees memory acquired with AcquireMagickMemory()
1042 % or AcquireQuantumMemory() for reuse.
1044 % The format of the RelinquishMagickMemory method is:
1046 % void *RelinquishMagickMemory(void *memory)
1048 % A description of each parameter follows:
1050 % o memory: A pointer to a block of memory to free for reuse.
1053 MagickExport void *RelinquishMagickMemory(void *memory)
1055 if (memory == (void *) NULL)
1056 return((void *) NULL);
1057 #if !defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
1058 memory_methods.destroy_memory_handler(memory);
1060 LockSemaphoreInfo(memory_semaphore);
1061 assert((SizeOfBlock(memory) % (4*sizeof(size_t))) == 0);
1062 assert((*BlockHeader(NextBlock(memory)) & PreviousBlockBit) != 0);
1063 if ((*BlockHeader(memory) & PreviousBlockBit) == 0)
1069 Coalesce with previous adjacent block.
1071 previous=PreviousBlock(memory);
1072 RemoveFreeBlock(previous,AllocationPolicy(SizeOfBlock(previous)));
1073 *BlockHeader(previous)=(SizeOfBlock(previous)+SizeOfBlock(memory)) |
1074 (*BlockHeader(previous) & ~SizeMask);
1077 if ((*BlockHeader(NextBlock(NextBlock(memory))) & PreviousBlockBit) == 0)
1083 Coalesce with next adjacent block.
1085 next=NextBlock(memory);
1086 RemoveFreeBlock(next,AllocationPolicy(SizeOfBlock(next)));
1087 *BlockHeader(memory)=(SizeOfBlock(memory)+SizeOfBlock(next)) |
1088 (*BlockHeader(memory) & ~SizeMask);
1090 *BlockFooter(memory,SizeOfBlock(memory))=SizeOfBlock(memory);
1091 *BlockHeader(NextBlock(memory))&=(~PreviousBlockBit);
1092 InsertFreeBlock(memory,AllocationPolicy(SizeOfBlock(memory)));
1093 UnlockSemaphoreInfo(memory_semaphore);
1095 return((void *) NULL);
1099 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1103 % R e l i n q u i s h V i r t u a l M e m o r y %
1107 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1109 % RelinquishVirtualMemory() frees memory acquired with AcquireVirtualMemory().
1111 % The format of the RelinquishVirtualMemory method is:
1113 % MemoryInfo *RelinquishVirtualMemory(MemoryInfo *memory_info)
1115 % A description of each parameter follows:
1117 % o memory_info: A pointer to a block of memory to free for reuse.
1120 MagickExport MemoryInfo *RelinquishVirtualMemory(MemoryInfo *memory_info)
1122 assert(memory_info != (MemoryInfo *) NULL);
1123 assert(memory_info->signature == MagickCoreSignature);
1124 if (memory_info->blob != (void *) NULL)
1125 switch (memory_info->type)
1127 case AlignedVirtualMemory:
1129 memory_info->blob=RelinquishAlignedMemory(memory_info->blob);
1132 case MapVirtualMemory:
1134 (void) UnmapBlob(memory_info->blob,memory_info->length);
1135 memory_info->blob=NULL;
1136 if (*memory_info->filename != '\0')
1137 (void) RelinquishUniqueFileResource(memory_info->filename);
1140 case UnalignedVirtualMemory:
1143 memory_info->blob=RelinquishMagickMemory(memory_info->blob);
1147 memory_info->signature=(~MagickCoreSignature);
1148 memory_info=(MemoryInfo *) RelinquishAlignedMemory(memory_info);
1149 return(memory_info);
1153 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1157 % R e s e t M a g i c k M e m o r y %
1161 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1163 % ResetMagickMemory() fills the first size bytes of the memory area pointed to
1164 % by memory with the constant byte c.
1166 % The format of the ResetMagickMemory method is:
1168 % void *ResetMagickMemory(void *memory,int byte,const size_t size)
1170 % A description of each parameter follows:
1172 % o memory: a pointer to a memory allocation.
1174 % o byte: set the memory to this value.
1176 % o size: size of the memory to reset.
1179 MagickExport void *ResetMagickMemory(void *memory,int byte,const size_t size)
1181 assert(memory != (void *) NULL);
1182 return(memset(memory,byte,size));
1186 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1190 + R e s e t M a x M e m o r y R e q u e s t %
1194 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1196 % ResetMaxMemoryRequest() resets the max_memory_request value.
1198 % The format of the ResetMaxMemoryRequest method is:
1200 % void ResetMaxMemoryRequest(void)
1203 MagickPrivate void ResetMaxMemoryRequest(void)
1205 max_memory_request=0;
1209 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1213 + R e s e t V i r t u a l A n o n y m o u s M e m o r y %
1217 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1219 % ResetVirtualAnonymousMemory() resets the virtual_anonymous_memory value.
1221 % The format of the ResetVirtualAnonymousMemory method is:
1223 % void ResetVirtualAnonymousMemory(void)
1226 MagickPrivate void ResetVirtualAnonymousMemory(void)
1228 virtual_anonymous_memory=0;
1232 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1236 % R e s i z e M a g i c k M e m o r y %
1240 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1242 % ResizeMagickMemory() changes the size of the memory and returns a pointer to
1243 % the (possibly moved) block. The contents will be unchanged up to the
1244 % lesser of the new and old sizes.
1246 % The format of the ResizeMagickMemory method is:
1248 % void *ResizeMagickMemory(void *memory,const size_t size)
1250 % A description of each parameter follows:
1252 % o memory: A pointer to a memory allocation.
1254 % o size: the new size of the allocated memory.
1258 #if defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
1259 static inline void *ResizeBlock(void *block,size_t size)
1264 if (block == (void *) NULL)
1265 return(AcquireBlock(size));
1266 memory=AcquireBlock(size);
1267 if (memory == (void *) NULL)
1268 return((void *) NULL);
1269 if (size <= (SizeOfBlock(block)-sizeof(size_t)))
1270 (void) memcpy(memory,block,size);
1272 (void) memcpy(memory,block,SizeOfBlock(block)-sizeof(size_t));
1273 memory_pool.allocation+=size;
1278 MagickExport void *ResizeMagickMemory(void *memory,const size_t size)
1283 if (memory == (void *) NULL)
1284 return(AcquireMagickMemory(size));
1285 #if !defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
1286 block=memory_methods.resize_memory_handler(memory,size == 0 ? 1UL : size);
1287 if (block == (void *) NULL)
1288 memory=RelinquishMagickMemory(memory);
1290 LockSemaphoreInfo(memory_semaphore);
1291 block=ResizeBlock(memory,size == 0 ? 1UL : size);
1292 if (block == (void *) NULL)
1294 if (ExpandHeap(size == 0 ? 1UL : size) == MagickFalse)
1296 UnlockSemaphoreInfo(memory_semaphore);
1297 memory=RelinquishMagickMemory(memory);
1298 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1300 block=ResizeBlock(memory,size == 0 ? 1UL : size);
1301 assert(block != (void *) NULL);
1303 UnlockSemaphoreInfo(memory_semaphore);
1304 memory=RelinquishMagickMemory(memory);
1310 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1314 % R e s i z e Q u a n t u m M e m o r y %
1318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1320 % ResizeQuantumMemory() changes the size of the memory and returns a pointer
1321 % to the (possibly moved) block. The contents will be unchanged up to the
1322 % lesser of the new and old sizes.
1324 % The format of the ResizeQuantumMemory method is:
1326 % void *ResizeQuantumMemory(void *memory,const size_t count,
1327 % const size_t quantum)
1329 % A description of each parameter follows:
1331 % o memory: A pointer to a memory allocation.
1333 % o count: the number of quantum elements to allocate.
1335 % o quantum: the number of bytes in each quantum.
1338 MagickExport void *ResizeQuantumMemory(void *memory,const size_t count,
1339 const size_t quantum)
1344 if (HeapOverflowSanityCheck(count,quantum) != MagickFalse)
1346 memory=RelinquishMagickMemory(memory);
1347 return((void *) NULL);
1349 extent=count*quantum;
1350 return(ResizeMagickMemory(memory,extent));
1354 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1358 % S e t M a g i c k M e m o r y M e t h o d s %
1362 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1364 % SetMagickMemoryMethods() sets the methods to acquire, resize, and destroy
1365 % memory. Your custom memory methods must be set prior to the
1366 % MagickCoreGenesis() method.
1368 % The format of the SetMagickMemoryMethods() method is:
1370 % SetMagickMemoryMethods(AcquireMemoryHandler acquire_memory_handler,
1371 % ResizeMemoryHandler resize_memory_handler,
1372 % DestroyMemoryHandler destroy_memory_handler)
1374 % A description of each parameter follows:
1376 % o acquire_memory_handler: method to acquire memory (e.g. malloc).
1378 % o resize_memory_handler: method to resize memory (e.g. realloc).
1380 % o destroy_memory_handler: method to destroy memory (e.g. free).
1383 MagickExport void SetMagickMemoryMethods(
1384 AcquireMemoryHandler acquire_memory_handler,
1385 ResizeMemoryHandler resize_memory_handler,
1386 DestroyMemoryHandler destroy_memory_handler)
1391 if (acquire_memory_handler != (AcquireMemoryHandler) NULL)
1392 memory_methods.acquire_memory_handler=acquire_memory_handler;
1393 if (resize_memory_handler != (ResizeMemoryHandler) NULL)
1394 memory_methods.resize_memory_handler=resize_memory_handler;
1395 if (destroy_memory_handler != (DestroyMemoryHandler) NULL)
1396 memory_methods.destroy_memory_handler=destroy_memory_handler;