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-2013 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 % http://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_ZERO_CONFIGURATION_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/resource_.h"
64 #include "MagickCore/semaphore.h"
65 #include "MagickCore/string_.h"
66 #include "MagickCore/utility-private.h"
71 #define BlockFooter(block,size) \
72 ((size_t *) ((char *) (block)+(size)-2*sizeof(size_t)))
73 #define BlockHeader(block) ((size_t *) (block)-1)
74 #define BlockSize 4096
75 #define BlockThreshold 1024
76 #define MaxBlockExponent 16
77 #define MaxBlocks ((BlockThreshold/(4*sizeof(size_t)))+MaxBlockExponent+1)
78 #define MaxSegments 1024
79 #define MemoryGuard ((0xdeadbeef << 31)+0xdeafdeed)
80 #define NextBlock(block) ((char *) (block)+SizeOfBlock(block))
81 #define NextBlockInList(block) (*(void **) (block))
82 #define PreviousBlock(block) ((char *) (block)-(*((size_t *) (block)-2)))
83 #define PreviousBlockBit 0x01
84 #define PreviousBlockInList(block) (*((void **) (block)+1))
85 #define SegmentSize (2*1024*1024)
86 #define SizeMask (~0x01)
87 #define SizeOfBlock(block) (*BlockHeader(block) & SizeMask)
92 typedef struct _DataSegmentInfo
104 struct _DataSegmentInfo
109 typedef struct _MagickMemoryMethods
112 acquire_memory_handler;
115 resize_memory_handler;
118 destroy_memory_handler;
119 } MagickMemoryMethods;
124 filename[MaxTextExtent];
139 typedef struct _MemoryPool
145 *blocks[MaxBlocks+1];
151 *segments[MaxSegments],
152 segment_pool[MaxSegments];
158 static MagickMemoryMethods
161 (AcquireMemoryHandler) malloc,
162 (ResizeMemoryHandler) realloc,
163 (DestroyMemoryHandler) free
166 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
171 *memory_semaphore = (SemaphoreInfo *) NULL;
173 static volatile DataSegmentInfo
174 *free_segments = (DataSegmentInfo *) NULL;
177 Forward declarations.
179 static MagickBooleanType
184 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
188 % A c q u i r e A l i g n e d M e m o r y %
192 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
194 % AcquireAlignedMemory() returns a pointer to a block of memory at least size
195 % bytes whose address is a multiple of 16*sizeof(void *).
197 % The format of the AcquireAlignedMemory method is:
199 % void *AcquireAlignedMemory(const size_t count,const size_t quantum)
201 % A description of each parameter follows:
203 % o count: the number of quantum elements to allocate.
205 % o quantum: the number of bytes in each quantum.
208 MagickExport void *AcquireAlignedMemory(const size_t count,const size_t quantum)
210 #define AlignedExtent(size,alignment) \
211 (((size)+((alignment)-1)) & ~((alignment)-1))
222 if ((count == 0) || (quantum != (size/count)))
225 return((void *) NULL);
228 alignment=CACHE_LINE_SIZE;
229 extent=AlignedExtent(size,alignment);
230 if ((size == 0) || (alignment < sizeof(void *)) || (extent < size))
231 return((void *) NULL);
232 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
233 if (posix_memalign(&memory,alignment,extent) != 0)
235 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
236 memory=_aligned_malloc(extent,alignment);
242 extent=(size+alignment-1)+sizeof(void *);
248 memory=(void *) AlignedExtent((size_t) p+sizeof(void *),alignment);
249 *((void **) memory-1)=p;
257 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
259 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
263 + A c q u i r e B l o c k %
267 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
269 % AcquireBlock() returns a pointer to a block of memory at least size bytes
270 % suitably aligned for any use.
272 % The format of the AcquireBlock method is:
274 % void *AcquireBlock(const size_t size)
276 % A description of each parameter follows:
278 % o size: the size of the memory in bytes to allocate.
282 static inline size_t AllocationPolicy(size_t size)
288 The linear distribution.
291 assert(size % (4*sizeof(size_t)) == 0);
292 if (size <= BlockThreshold)
293 return(size/(4*sizeof(size_t)));
295 Check for the largest block size.
297 if (size > (size_t) (BlockThreshold*(1L << (MaxBlockExponent-1L))))
298 return(MaxBlocks-1L);
300 Otherwise use a power of two distribution.
302 blocksize=BlockThreshold/(4*sizeof(size_t));
303 for ( ; size > BlockThreshold; size/=2)
305 assert(blocksize > (BlockThreshold/(4*sizeof(size_t))));
306 assert(blocksize < (MaxBlocks-1L));
310 static inline void InsertFreeBlock(void *block,const size_t i)
319 size=SizeOfBlock(block);
320 previous=(void *) NULL;
321 next=memory_pool.blocks[i];
322 while ((next != (void *) NULL) && (SizeOfBlock(next) < size))
325 next=NextBlockInList(next);
327 PreviousBlockInList(block)=previous;
328 NextBlockInList(block)=next;
329 if (previous != (void *) NULL)
330 NextBlockInList(previous)=block;
332 memory_pool.blocks[i]=block;
333 if (next != (void *) NULL)
334 PreviousBlockInList(next)=block;
337 static inline void RemoveFreeBlock(void *block,const size_t i)
343 next=NextBlockInList(block);
344 previous=PreviousBlockInList(block);
345 if (previous == (void *) NULL)
346 memory_pool.blocks[i]=next;
348 NextBlockInList(previous)=next;
349 if (next != (void *) NULL)
350 PreviousBlockInList(next)=previous;
353 static void *AcquireBlock(size_t size)
364 size=(size_t) (size+sizeof(size_t)+6*sizeof(size_t)-1) & -(4U*sizeof(size_t));
365 i=AllocationPolicy(size);
366 block=memory_pool.blocks[i];
367 while ((block != (void *) NULL) && (SizeOfBlock(block) < size))
368 block=NextBlockInList(block);
369 if (block == (void *) NULL)
372 while (memory_pool.blocks[i] == (void *) NULL)
374 block=memory_pool.blocks[i];
376 return((void *) NULL);
378 assert((*BlockHeader(NextBlock(block)) & PreviousBlockBit) == 0);
379 assert(SizeOfBlock(block) >= size);
380 RemoveFreeBlock(block,AllocationPolicy(SizeOfBlock(block)));
381 if (SizeOfBlock(block) > size)
392 next=(char *) block+size;
393 blocksize=SizeOfBlock(block)-size;
394 *BlockHeader(next)=blocksize;
395 *BlockFooter(next,blocksize)=blocksize;
396 InsertFreeBlock(next,AllocationPolicy(blocksize));
397 *BlockHeader(block)=size | (*BlockHeader(block) & ~SizeMask);
399 assert(size == SizeOfBlock(block));
400 *BlockHeader(NextBlock(block))|=PreviousBlockBit;
401 memory_pool.allocation+=size;
407 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
411 % A c q u i r e M a g i c k M e m o r y %
415 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
417 % AcquireMagickMemory() returns a pointer to a block of memory at least size
418 % bytes suitably aligned for any use.
420 % The format of the AcquireMagickMemory method is:
422 % void *AcquireMagickMemory(const size_t size)
424 % A description of each parameter follows:
426 % o size: the size of the memory in bytes to allocate.
429 MagickExport void *AcquireMagickMemory(const size_t size)
434 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
435 memory=memory_methods.acquire_memory_handler(size == 0 ? 1UL : size);
437 if (memory_semaphore == (SemaphoreInfo *) NULL)
438 AcquireSemaphoreInfo(&memory_semaphore);
439 if (free_segments == (DataSegmentInfo *) NULL)
441 LockSemaphoreInfo(memory_semaphore);
442 if (free_segments == (DataSegmentInfo *) NULL)
447 assert(2*sizeof(size_t) > (size_t) (~SizeMask));
448 (void) ResetMagickMemory(&memory_pool,0,sizeof(memory_pool));
449 memory_pool.allocation=SegmentSize;
450 memory_pool.blocks[MaxBlocks]=(void *) (-1);
451 for (i=0; i < MaxSegments; i++)
454 memory_pool.segment_pool[i].previous=
455 (&memory_pool.segment_pool[i-1]);
456 if (i != (MaxSegments-1))
457 memory_pool.segment_pool[i].next=(&memory_pool.segment_pool[i+1]);
459 free_segments=(&memory_pool.segment_pool[0]);
461 UnlockSemaphoreInfo(memory_semaphore);
463 LockSemaphoreInfo(memory_semaphore);
464 memory=AcquireBlock(size == 0 ? 1UL : size);
465 if (memory == (void *) NULL)
467 if (ExpandHeap(size == 0 ? 1UL : size) != MagickFalse)
468 memory=AcquireBlock(size == 0 ? 1UL : size);
470 UnlockSemaphoreInfo(memory_semaphore);
476 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
480 % A c q u i r e Q u a n t u m M e m o r y %
484 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
486 % AcquireQuantumMemory() returns a pointer to a block of memory at least
487 % count * quantum bytes suitably aligned for any use.
489 % The format of the AcquireQuantumMemory method is:
491 % void *AcquireQuantumMemory(const size_t count,const size_t quantum)
493 % A description of each parameter follows:
495 % o count: the number of quantum elements to allocate.
497 % o quantum: the number of bytes in each quantum.
500 MagickExport void *AcquireQuantumMemory(const size_t count,const size_t quantum)
506 if ((count == 0) || (quantum != (size/count)))
509 return((void *) NULL);
511 return(AcquireMagickMemory(size));
515 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
519 % A c q u i r e V i r t u a l M e m o r y %
523 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
525 % AcquireVirtualMemory() allocates a pointer to a block of memory at least size
526 % bytes suitably aligned for any use.
528 % The format of the AcquireVirtualMemory method is:
530 % MemoryInfo *AcquireVirtualMemory(const size_t count,const size_t quantum)
532 % A description of each parameter follows:
534 % o count: the number of quantum elements to allocate.
536 % o quantum: the number of bytes in each quantum.
539 MagickExport MemoryInfo *AcquireVirtualMemory(const size_t count,
540 const size_t quantum)
548 length=count*quantum;
549 if ((count == 0) || (quantum != (length/count)))
552 return((MemoryInfo *) NULL);
554 memory_info=(MemoryInfo *) MagickAssumeAligned(AcquireAlignedMemory(1,
555 sizeof(*memory_info)));
556 if (memory_info == (MemoryInfo *) NULL)
557 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
558 (void) ResetMagickMemory(memory_info,0,sizeof(*memory_info));
559 memory_info->length=length;
560 memory_info->signature=MagickSignature;
561 if (AcquireMagickResource(MemoryResource,length) != MagickFalse)
563 memory_info->blob=AcquireMagickMemory(length);
564 if (memory_info->blob == NULL)
565 RelinquishMagickResource(MemoryResource,length);
567 if ((memory_info->blob == NULL) &&
568 (AcquireMagickResource(MapResource,length) != MagickFalse))
571 Heap memory failed, try anonymous memory mapping.
573 memory_info->mapped=MagickTrue;
574 memory_info->blob=MapBlob(-1,IOMode,0,length);
575 if (memory_info->blob == NULL)
576 RelinquishMagickResource(MapResource,length);
578 if (memory_info->blob == NULL)
584 Anonymous memory mapping failed, try file-backed memory mapping.
586 file=AcquireUniqueFileResource(memory_info->filename);
587 file=open_utf8(memory_info->filename,O_RDWR | O_CREAT | O_BINARY | O_EXCL,
590 file=open_utf8(memory_info->filename,O_RDWR | O_BINARY,S_MODE);
593 if ((lseek(file,length-1,SEEK_SET) >= 0) && (write(file,"",1) == 1))
595 (void) AcquireMagickResource(MapResource,length);
596 memory_info->mapped=MagickTrue;
597 memory_info->blob=MapBlob(file,IOMode,0,length);
598 if (memory_info->blob == NULL)
599 RelinquishMagickResource(MapResource,length);
604 if (memory_info->blob == NULL)
605 return(RelinquishVirtualMemory(memory_info));
610 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
614 % C o p y M a g i c k M e m o r y %
618 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
620 % CopyMagickMemory() copies size bytes from memory area source to the
621 % destination. Copying between objects that overlap will take place
622 % correctly. It returns destination.
624 % The format of the CopyMagickMemory method is:
626 % void *CopyMagickMemory(void *destination,const void *source,
629 % A description of each parameter follows:
631 % o destination: the destination.
633 % o source: the source.
635 % o size: the size of the memory in bytes to allocate.
638 MagickExport void *CopyMagickMemory(void *destination,const void *source,
641 register const unsigned char
644 register unsigned char
647 assert(destination != (void *) NULL);
648 assert(source != (const void *) NULL);
649 p=(const unsigned char *) source;
650 q=(unsigned char *) destination;
651 if (((q+size) < p) || (q > (p+size)))
654 default: return(memcpy(destination,source,size));
663 case 0: return(destination);
665 return(memmove(destination,source,size));
669 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
673 + D e s t r o y M a g i c k M e m o r y %
677 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
679 % DestroyMagickMemory() deallocates memory associated with the memory manager.
681 % The format of the DestroyMagickMemory method is:
683 % DestroyMagickMemory(void)
686 MagickExport void DestroyMagickMemory(void)
688 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
692 if (memory_semaphore == (SemaphoreInfo *) NULL)
693 AcquireSemaphoreInfo(&memory_semaphore);
694 LockSemaphoreInfo(memory_semaphore);
695 UnlockSemaphoreInfo(memory_semaphore);
696 for (i=0; i < (ssize_t) memory_pool.number_segments; i++)
697 if (memory_pool.segments[i]->mapped == MagickFalse)
698 memory_methods.destroy_memory_handler(
699 memory_pool.segments[i]->allocation);
701 (void) UnmapBlob(memory_pool.segments[i]->allocation,
702 memory_pool.segments[i]->length);
703 free_segments=(DataSegmentInfo *) NULL;
704 (void) ResetMagickMemory(&memory_pool,0,sizeof(memory_pool));
705 DestroySemaphoreInfo(&memory_semaphore);
709 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
711 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
715 + E x p a n d H e a p %
719 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
721 % ExpandHeap() get more memory from the system. It returns MagickTrue on
722 % success otherwise MagickFalse.
724 % The format of the ExpandHeap method is:
726 % MagickBooleanType ExpandHeap(size_t size)
728 % A description of each parameter follows:
730 % o size: the size of the memory in bytes we require.
733 static MagickBooleanType ExpandHeap(size_t size)
753 blocksize=((size+12*sizeof(size_t))+SegmentSize-1) & -SegmentSize;
754 assert(memory_pool.number_segments < MaxSegments);
755 segment=MapBlob(-1,IOMode,0,blocksize);
756 mapped=segment != (void *) NULL ? MagickTrue : MagickFalse;
757 if (segment == (void *) NULL)
758 segment=(void *) memory_methods.acquire_memory_handler(blocksize);
759 if (segment == (void *) NULL)
761 segment_info=(DataSegmentInfo *) free_segments;
762 free_segments=segment_info->next;
763 segment_info->mapped=mapped;
764 segment_info->length=blocksize;
765 segment_info->allocation=segment;
766 segment_info->bound=(char *) segment+blocksize;
767 i=(ssize_t) memory_pool.number_segments-1;
768 for ( ; (i >= 0) && (memory_pool.segments[i]->allocation > segment); i--)
769 memory_pool.segments[i+1]=memory_pool.segments[i];
770 memory_pool.segments[i+1]=segment_info;
771 memory_pool.number_segments++;
772 size=blocksize-12*sizeof(size_t);
773 block=(char *) segment_info->allocation+4*sizeof(size_t);
774 *BlockHeader(block)=size | PreviousBlockBit;
775 *BlockFooter(block,size)=size;
776 InsertFreeBlock(block,AllocationPolicy(size));
777 block=NextBlock(block);
778 assert(block < segment_info->bound);
779 *BlockHeader(block)=2*sizeof(size_t);
780 *BlockHeader(NextBlock(block))=PreviousBlockBit;
786 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
790 % G e t M a g i c k M e m o r y M e t h o d s %
794 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
796 % GetMagickMemoryMethods() gets the methods to acquire, resize, and destroy
799 % The format of the GetMagickMemoryMethods() method is:
801 % void GetMagickMemoryMethods(AcquireMemoryHandler *acquire_memory_handler,
802 % ResizeMemoryHandler *resize_memory_handler,
803 % DestroyMemoryHandler *destroy_memory_handler)
805 % A description of each parameter follows:
807 % o acquire_memory_handler: method to acquire memory (e.g. malloc).
809 % o resize_memory_handler: method to resize memory (e.g. realloc).
811 % o destroy_memory_handler: method to destroy memory (e.g. free).
814 MagickExport void GetMagickMemoryMethods(
815 AcquireMemoryHandler *acquire_memory_handler,
816 ResizeMemoryHandler *resize_memory_handler,
817 DestroyMemoryHandler *destroy_memory_handler)
819 assert(acquire_memory_handler != (AcquireMemoryHandler *) NULL);
820 assert(resize_memory_handler != (ResizeMemoryHandler *) NULL);
821 assert(destroy_memory_handler != (DestroyMemoryHandler *) NULL);
822 *acquire_memory_handler=memory_methods.acquire_memory_handler;
823 *resize_memory_handler=memory_methods.resize_memory_handler;
824 *destroy_memory_handler=memory_methods.destroy_memory_handler;
828 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
832 % G e t V i r t u a l M e m o r y B l o b %
836 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
838 % GetVirtualMemoryBlob() returns the virtual memory blob associated with the
839 % specified MemoryInfo structure.
841 % The format of the GetVirtualMemoryBlob method is:
843 % void *GetVirtualMemoryBlob(const MemoryInfo *memory_info)
845 % A description of each parameter follows:
847 % o memory_info: The MemoryInfo structure.
849 MagickExport void *GetVirtualMemoryBlob(const MemoryInfo *memory_info)
851 assert(memory_info != (const MemoryInfo *) NULL);
852 assert(memory_info->signature == MagickSignature);
853 return(memory_info->blob);
857 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
861 % R e l i n q u i s h A l i g n e d M e m o r y %
865 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
867 % RelinquishAlignedMemory() frees memory acquired with AcquireAlignedMemory()
870 % The format of the RelinquishAlignedMemory method is:
872 % void *RelinquishAlignedMemory(void *memory)
874 % A description of each parameter follows:
876 % o memory: A pointer to a block of memory to free for reuse.
879 MagickExport void *RelinquishAlignedMemory(void *memory)
881 if (memory == (void *) NULL)
882 return((void *) NULL);
883 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
885 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
886 _aligned_free(memory);
888 free(*((void **) memory-1));
894 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
898 % R e l i n q u i s h M a g i c k M e m o r y %
902 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
904 % RelinquishMagickMemory() frees memory acquired with AcquireMagickMemory()
905 % or AcquireQuantumMemory() for reuse.
907 % The format of the RelinquishMagickMemory method is:
909 % void *RelinquishMagickMemory(void *memory)
911 % A description of each parameter follows:
913 % o memory: A pointer to a block of memory to free for reuse.
916 MagickExport void *RelinquishMagickMemory(void *memory)
918 if (memory == (void *) NULL)
919 return((void *) NULL);
920 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
921 memory_methods.destroy_memory_handler(memory);
923 LockSemaphoreInfo(memory_semaphore);
924 assert((SizeOfBlock(memory) % (4*sizeof(size_t))) == 0);
925 assert((*BlockHeader(NextBlock(memory)) & PreviousBlockBit) != 0);
926 if ((*BlockHeader(memory) & PreviousBlockBit) == 0)
932 Coalesce with previous adjacent block.
934 previous=PreviousBlock(memory);
935 RemoveFreeBlock(previous,AllocationPolicy(SizeOfBlock(previous)));
936 *BlockHeader(previous)=(SizeOfBlock(previous)+SizeOfBlock(memory)) |
937 (*BlockHeader(previous) & ~SizeMask);
940 if ((*BlockHeader(NextBlock(NextBlock(memory))) & PreviousBlockBit) == 0)
946 Coalesce with next adjacent block.
948 next=NextBlock(memory);
949 RemoveFreeBlock(next,AllocationPolicy(SizeOfBlock(next)));
950 *BlockHeader(memory)=(SizeOfBlock(memory)+SizeOfBlock(next)) |
951 (*BlockHeader(memory) & ~SizeMask);
953 *BlockFooter(memory,SizeOfBlock(memory))=SizeOfBlock(memory);
954 *BlockHeader(NextBlock(memory))&=(~PreviousBlockBit);
955 InsertFreeBlock(memory,AllocationPolicy(SizeOfBlock(memory)));
956 UnlockSemaphoreInfo(memory_semaphore);
958 return((void *) NULL);
962 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
966 % R e l i n q u i s h V i r t u a l M e m o r y %
970 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
972 % RelinquishVirtualMemory() frees memory acquired with AcquireVirtualMemory().
974 % The format of the RelinquishVirtualMemory method is:
976 % MemoryInfo *RelinquishVirtualMemory(MemoryInfo *memory_info)
978 % A description of each parameter follows:
980 % o memory_info: A pointer to a block of memory to free for reuse.
983 MagickExport MemoryInfo *RelinquishVirtualMemory(MemoryInfo *memory_info)
985 assert(memory_info != (MemoryInfo *) NULL);
986 assert(memory_info->signature == MagickSignature);
987 if (memory_info->blob != (void *) NULL)
989 if (memory_info->mapped == MagickFalse)
991 memory_info->blob=RelinquishMagickMemory(memory_info->blob);
992 RelinquishMagickResource(MemoryResource,memory_info->length);
996 (void) UnmapBlob(memory_info->blob,memory_info->length);
997 RelinquishMagickResource(MapResource,memory_info->length);
998 memory_info->blob=NULL;
999 if (*memory_info->filename != '\0')
1000 (void) RelinquishUniqueFileResource(memory_info->filename);
1003 memory_info->signature=(~MagickSignature);
1004 memory_info=(MemoryInfo *) RelinquishAlignedMemory(memory_info);
1005 return(memory_info);
1009 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1013 % R e s e t M a g i c k M e m o r y %
1017 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1019 % ResetMagickMemory() fills the first size bytes of the memory area pointed to
1020 % by memory with the constant byte c.
1022 % The format of the ResetMagickMemory method is:
1024 % void *ResetMagickMemory(void *memory,int byte,const size_t size)
1026 % A description of each parameter follows:
1028 % o memory: a pointer to a memory allocation.
1030 % o byte: set the memory to this value.
1032 % o size: size of the memory to reset.
1035 MagickExport void *ResetMagickMemory(void *memory,int byte,const size_t size)
1037 assert(memory != (void *) NULL);
1038 return(memset(memory,byte,size));
1042 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1046 % R e s i z e M a g i c k M e m o r y %
1050 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1052 % ResizeMagickMemory() changes the size of the memory and returns a pointer to
1053 % the (possibly moved) block. The contents will be unchanged up to the
1054 % lesser of the new and old sizes.
1056 % The format of the ResizeMagickMemory method is:
1058 % void *ResizeMagickMemory(void *memory,const size_t size)
1060 % A description of each parameter follows:
1062 % o memory: A pointer to a memory allocation.
1064 % o size: the new size of the allocated memory.
1068 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
1069 static inline void *ResizeBlock(void *block,size_t size)
1074 if (block == (void *) NULL)
1075 return(AcquireBlock(size));
1076 memory=AcquireBlock(size);
1077 if (memory == (void *) NULL)
1078 return((void *) NULL);
1079 if (size <= (SizeOfBlock(block)-sizeof(size_t)))
1080 (void) memcpy(memory,block,size);
1082 (void) memcpy(memory,block,SizeOfBlock(block)-sizeof(size_t));
1083 memory_pool.allocation+=size;
1088 MagickExport void *ResizeMagickMemory(void *memory,const size_t size)
1093 if (memory == (void *) NULL)
1094 return(AcquireMagickMemory(size));
1095 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
1096 block=memory_methods.resize_memory_handler(memory,size == 0 ? 1UL : size);
1097 if (block == (void *) NULL)
1098 memory=RelinquishMagickMemory(memory);
1100 LockSemaphoreInfo(memory_semaphore);
1101 block=ResizeBlock(memory,size == 0 ? 1UL : size);
1102 if (block == (void *) NULL)
1104 if (ExpandHeap(size == 0 ? 1UL : size) == MagickFalse)
1106 UnlockSemaphoreInfo(memory_semaphore);
1107 memory=RelinquishMagickMemory(memory);
1108 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1110 block=ResizeBlock(memory,size == 0 ? 1UL : size);
1111 assert(block != (void *) NULL);
1113 UnlockSemaphoreInfo(memory_semaphore);
1114 memory=RelinquishMagickMemory(memory);
1120 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1124 % R e s i z e Q u a n t u m M e m o r y %
1128 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1130 % ResizeQuantumMemory() changes the size of the memory and returns a pointer
1131 % to the (possibly moved) block. The contents will be unchanged up to the
1132 % lesser of the new and old sizes.
1134 % The format of the ResizeQuantumMemory method is:
1136 % void *ResizeQuantumMemory(void *memory,const size_t count,
1137 % const size_t quantum)
1139 % A description of each parameter follows:
1141 % o memory: A pointer to a memory allocation.
1143 % o count: the number of quantum elements to allocate.
1145 % o quantum: the number of bytes in each quantum.
1148 MagickExport void *ResizeQuantumMemory(void *memory,const size_t count,
1149 const size_t quantum)
1155 if ((count == 0) || (quantum != (size/count)))
1157 memory=RelinquishMagickMemory(memory);
1159 return((void *) NULL);
1161 return(ResizeMagickMemory(memory,size));
1165 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1169 % S e t M a g i c k M e m o r y M e t h o d s %
1173 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1175 % SetMagickMemoryMethods() sets the methods to acquire, resize, and destroy
1176 % memory. Your custom memory methods must be set prior to the
1177 % MagickCoreGenesis() method.
1179 % The format of the SetMagickMemoryMethods() method is:
1181 % SetMagickMemoryMethods(AcquireMemoryHandler acquire_memory_handler,
1182 % ResizeMemoryHandler resize_memory_handler,
1183 % DestroyMemoryHandler destroy_memory_handler)
1185 % A description of each parameter follows:
1187 % o acquire_memory_handler: method to acquire memory (e.g. malloc).
1189 % o resize_memory_handler: method to resize memory (e.g. realloc).
1191 % o destroy_memory_handler: method to destroy memory (e.g. free).
1194 MagickExport void SetMagickMemoryMethods(
1195 AcquireMemoryHandler acquire_memory_handler,
1196 ResizeMemoryHandler resize_memory_handler,
1197 DestroyMemoryHandler destroy_memory_handler)
1202 if (acquire_memory_handler != (AcquireMemoryHandler) NULL)
1203 memory_methods.acquire_memory_handler=acquire_memory_handler;
1204 if (resize_memory_handler != (ResizeMemoryHandler) NULL)
1205 memory_methods.resize_memory_handler=resize_memory_handler;
1206 if (destroy_memory_handler != (DestroyMemoryHandler) NULL)
1207 memory_methods.destroy_memory_handler=destroy_memory_handler;