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)
94 UndefinedVirtualMemory,
97 UnalignedVirtualMemory
100 typedef struct _DataSegmentInfo
112 struct _DataSegmentInfo
117 typedef struct _MagickMemoryMethods
120 acquire_memory_handler;
123 resize_memory_handler;
126 destroy_memory_handler;
127 } MagickMemoryMethods;
132 filename[MaxTextExtent];
147 typedef struct _MemoryPool
153 *blocks[MaxBlocks+1];
159 *segments[MaxSegments],
160 segment_pool[MaxSegments];
166 static MagickMemoryMethods
169 (AcquireMemoryHandler) malloc,
170 (ResizeMemoryHandler) realloc,
171 (DestroyMemoryHandler) free
174 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
179 *memory_semaphore = (SemaphoreInfo *) NULL;
181 static volatile DataSegmentInfo
182 *free_segments = (DataSegmentInfo *) NULL;
185 Forward declarations.
187 static MagickBooleanType
192 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
196 % A c q u i r e A l i g n e d M e m o r y %
200 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
202 % AcquireAlignedMemory() returns a pointer to a block of memory at least size
203 % bytes whose address is a multiple of 16*sizeof(void *).
205 % The format of the AcquireAlignedMemory method is:
207 % void *AcquireAlignedMemory(const size_t count,const size_t quantum)
209 % A description of each parameter follows:
211 % o count: the number of quantum elements to allocate.
213 % o quantum: the number of bytes in each quantum.
216 MagickExport void *AcquireAlignedMemory(const size_t count,const size_t quantum)
218 #define AlignedExtent(size,alignment) \
219 (((size)+((alignment)-1)) & ~((alignment)-1))
230 if ((count == 0) || (quantum != (size/count)))
233 return((void *) NULL);
236 alignment=CACHE_LINE_SIZE;
237 extent=AlignedExtent(size,alignment);
238 if ((size == 0) || (alignment < sizeof(void *)) || (extent < size))
239 return((void *) NULL);
240 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
241 if (posix_memalign(&memory,alignment,extent) != 0)
243 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
244 memory=_aligned_malloc(extent,alignment);
250 extent=(size+alignment-1)+sizeof(void *);
256 memory=(void *) AlignedExtent((size_t) p+sizeof(void *),alignment);
257 *((void **) memory-1)=p;
265 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
267 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
271 + A c q u i r e B l o c k %
275 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
277 % AcquireBlock() returns a pointer to a block of memory at least size bytes
278 % suitably aligned for any use.
280 % The format of the AcquireBlock method is:
282 % void *AcquireBlock(const size_t size)
284 % A description of each parameter follows:
286 % o size: the size of the memory in bytes to allocate.
290 static inline size_t AllocationPolicy(size_t size)
296 The linear distribution.
299 assert(size % (4*sizeof(size_t)) == 0);
300 if (size <= BlockThreshold)
301 return(size/(4*sizeof(size_t)));
303 Check for the largest block size.
305 if (size > (size_t) (BlockThreshold*(1L << (MaxBlockExponent-1L))))
306 return(MaxBlocks-1L);
308 Otherwise use a power of two distribution.
310 blocksize=BlockThreshold/(4*sizeof(size_t));
311 for ( ; size > BlockThreshold; size/=2)
313 assert(blocksize > (BlockThreshold/(4*sizeof(size_t))));
314 assert(blocksize < (MaxBlocks-1L));
318 static inline void InsertFreeBlock(void *block,const size_t i)
327 size=SizeOfBlock(block);
328 previous=(void *) NULL;
329 next=memory_pool.blocks[i];
330 while ((next != (void *) NULL) && (SizeOfBlock(next) < size))
333 next=NextBlockInList(next);
335 PreviousBlockInList(block)=previous;
336 NextBlockInList(block)=next;
337 if (previous != (void *) NULL)
338 NextBlockInList(previous)=block;
340 memory_pool.blocks[i]=block;
341 if (next != (void *) NULL)
342 PreviousBlockInList(next)=block;
345 static inline void RemoveFreeBlock(void *block,const size_t i)
351 next=NextBlockInList(block);
352 previous=PreviousBlockInList(block);
353 if (previous == (void *) NULL)
354 memory_pool.blocks[i]=next;
356 NextBlockInList(previous)=next;
357 if (next != (void *) NULL)
358 PreviousBlockInList(next)=previous;
361 static void *AcquireBlock(size_t size)
372 size=(size_t) (size+sizeof(size_t)+6*sizeof(size_t)-1) & -(4U*sizeof(size_t));
373 i=AllocationPolicy(size);
374 block=memory_pool.blocks[i];
375 while ((block != (void *) NULL) && (SizeOfBlock(block) < size))
376 block=NextBlockInList(block);
377 if (block == (void *) NULL)
380 while (memory_pool.blocks[i] == (void *) NULL)
382 block=memory_pool.blocks[i];
384 return((void *) NULL);
386 assert((*BlockHeader(NextBlock(block)) & PreviousBlockBit) == 0);
387 assert(SizeOfBlock(block) >= size);
388 RemoveFreeBlock(block,AllocationPolicy(SizeOfBlock(block)));
389 if (SizeOfBlock(block) > size)
400 next=(char *) block+size;
401 blocksize=SizeOfBlock(block)-size;
402 *BlockHeader(next)=blocksize;
403 *BlockFooter(next,blocksize)=blocksize;
404 InsertFreeBlock(next,AllocationPolicy(blocksize));
405 *BlockHeader(block)=size | (*BlockHeader(block) & ~SizeMask);
407 assert(size == SizeOfBlock(block));
408 *BlockHeader(NextBlock(block))|=PreviousBlockBit;
409 memory_pool.allocation+=size;
415 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
419 % A c q u i r e M a g i c k M e m o r y %
423 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
425 % AcquireMagickMemory() returns a pointer to a block of memory at least size
426 % bytes suitably aligned for any use.
428 % The format of the AcquireMagickMemory method is:
430 % void *AcquireMagickMemory(const size_t size)
432 % A description of each parameter follows:
434 % o size: the size of the memory in bytes to allocate.
437 MagickExport void *AcquireMagickMemory(const size_t size)
442 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
443 memory=memory_methods.acquire_memory_handler(size == 0 ? 1UL : size);
445 if (memory_semaphore == (SemaphoreInfo *) NULL)
446 AcquireSemaphoreInfo(&memory_semaphore);
447 if (free_segments == (DataSegmentInfo *) NULL)
449 LockSemaphoreInfo(memory_semaphore);
450 if (free_segments == (DataSegmentInfo *) NULL)
455 assert(2*sizeof(size_t) > (size_t) (~SizeMask));
456 (void) ResetMagickMemory(&memory_pool,0,sizeof(memory_pool));
457 memory_pool.allocation=SegmentSize;
458 memory_pool.blocks[MaxBlocks]=(void *) (-1);
459 for (i=0; i < MaxSegments; i++)
462 memory_pool.segment_pool[i].previous=
463 (&memory_pool.segment_pool[i-1]);
464 if (i != (MaxSegments-1))
465 memory_pool.segment_pool[i].next=(&memory_pool.segment_pool[i+1]);
467 free_segments=(&memory_pool.segment_pool[0]);
469 UnlockSemaphoreInfo(memory_semaphore);
471 LockSemaphoreInfo(memory_semaphore);
472 memory=AcquireBlock(size == 0 ? 1UL : size);
473 if (memory == (void *) NULL)
475 if (ExpandHeap(size == 0 ? 1UL : size) != MagickFalse)
476 memory=AcquireBlock(size == 0 ? 1UL : size);
478 UnlockSemaphoreInfo(memory_semaphore);
484 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
488 % A c q u i r e Q u a n t u m M e m o r y %
492 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
494 % AcquireQuantumMemory() returns a pointer to a block of memory at least
495 % count * quantum bytes suitably aligned for any use.
497 % The format of the AcquireQuantumMemory method is:
499 % void *AcquireQuantumMemory(const size_t count,const size_t quantum)
501 % A description of each parameter follows:
503 % o count: the number of quantum elements to allocate.
505 % o quantum: the number of bytes in each quantum.
508 MagickExport void *AcquireQuantumMemory(const size_t count,const size_t quantum)
514 if ((count == 0) || (quantum != (size/count)))
517 return((void *) NULL);
519 return(AcquireMagickMemory(size));
523 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
527 % A c q u i r e V i r t u a l M e m o r y %
531 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
533 % AcquireVirtualMemory() allocates a pointer to a block of memory at least size
534 % bytes suitably aligned for any use.
536 % The format of the AcquireVirtualMemory method is:
538 % MemoryInfo *AcquireVirtualMemory(const size_t count,const size_t quantum)
540 % A description of each parameter follows:
542 % o count: the number of quantum elements to allocate.
544 % o quantum: the number of bytes in each quantum.
547 MagickExport MemoryInfo *AcquireVirtualMemory(const size_t count,
548 const size_t quantum)
556 length=count*quantum;
557 if ((count == 0) || (quantum != (length/count)))
560 return((MemoryInfo *) NULL);
562 memory_info=(MemoryInfo *) MagickAssumeAligned(AcquireAlignedMemory(1,
563 sizeof(*memory_info)));
564 if (memory_info == (MemoryInfo *) NULL)
565 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
566 (void) ResetMagickMemory(memory_info,0,sizeof(*memory_info));
567 memory_info->length=length;
568 memory_info->signature=MagickSignature;
569 if (AcquireMagickResource(MemoryResource,length) != MagickFalse)
571 memory_info->blob=AcquireAlignedMemory(1,length);
572 if (memory_info->blob != NULL)
573 memory_info->type=AlignedVirtualMemory;
575 RelinquishMagickResource(MemoryResource,length);
577 if ((memory_info->blob == NULL) &&
578 (AcquireMagickResource(MapResource,length) != MagickFalse))
581 Heap memory failed, try anonymous memory mapping.
583 memory_info->blob=MapBlob(-1,IOMode,0,length);
584 if (memory_info->blob != NULL)
585 memory_info->type=MapVirtualMemory;
587 RelinquishMagickResource(MapResource,length);
589 if (memory_info->blob == NULL)
595 Anonymous memory mapping failed, try file-backed memory mapping.
597 file=AcquireUniqueFileResource(memory_info->filename);
600 if ((lseek(file,length-1,SEEK_SET) >= 0) && (write(file,"",1) == 1))
602 memory_info->blob=MapBlob(file,IOMode,0,length);
603 if (memory_info->blob != NULL)
605 memory_info->type=MapVirtualMemory;
606 (void) AcquireMagickResource(MapResource,length);
612 if (memory_info->blob == NULL)
614 memory_info->blob=AcquireMagickMemory(length);
615 if (memory_info->blob != NULL)
616 memory_info->type=UnalignedVirtualMemory;
622 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
626 % C o p y M a g i c k M e m o r y %
630 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
632 % CopyMagickMemory() copies size bytes from memory area source to the
633 % destination. Copying between objects that overlap will take place
634 % correctly. It returns destination.
636 % The format of the CopyMagickMemory method is:
638 % void *CopyMagickMemory(void *destination,const void *source,
641 % A description of each parameter follows:
643 % o destination: the destination.
645 % o source: the source.
647 % o size: the size of the memory in bytes to allocate.
650 MagickExport void *CopyMagickMemory(void *destination,const void *source,
653 register const unsigned char
656 register unsigned char
659 assert(destination != (void *) NULL);
660 assert(source != (const void *) NULL);
661 p=(const unsigned char *) source;
662 q=(unsigned char *) destination;
663 if (((q+size) < p) || (q > (p+size)))
666 default: return(memcpy(destination,source,size));
675 case 0: return(destination);
677 return(memmove(destination,source,size));
681 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
685 + D e s t r o y M a g i c k M e m o r y %
689 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
691 % DestroyMagickMemory() deallocates memory associated with the memory manager.
693 % The format of the DestroyMagickMemory method is:
695 % DestroyMagickMemory(void)
698 MagickExport void DestroyMagickMemory(void)
700 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
704 if (memory_semaphore == (SemaphoreInfo *) NULL)
705 AcquireSemaphoreInfo(&memory_semaphore);
706 LockSemaphoreInfo(memory_semaphore);
707 UnlockSemaphoreInfo(memory_semaphore);
708 for (i=0; i < (ssize_t) memory_pool.number_segments; i++)
709 if (memory_pool.segments[i]->mapped == MagickFalse)
710 memory_methods.destroy_memory_handler(
711 memory_pool.segments[i]->allocation);
713 (void) UnmapBlob(memory_pool.segments[i]->allocation,
714 memory_pool.segments[i]->length);
715 free_segments=(DataSegmentInfo *) NULL;
716 (void) ResetMagickMemory(&memory_pool,0,sizeof(memory_pool));
717 DestroySemaphoreInfo(&memory_semaphore);
721 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
723 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
727 + E x p a n d H e a p %
731 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
733 % ExpandHeap() get more memory from the system. It returns MagickTrue on
734 % success otherwise MagickFalse.
736 % The format of the ExpandHeap method is:
738 % MagickBooleanType ExpandHeap(size_t size)
740 % A description of each parameter follows:
742 % o size: the size of the memory in bytes we require.
745 static MagickBooleanType ExpandHeap(size_t size)
765 blocksize=((size+12*sizeof(size_t))+SegmentSize-1) & -SegmentSize;
766 assert(memory_pool.number_segments < MaxSegments);
767 segment=MapBlob(-1,IOMode,0,blocksize);
768 mapped=segment != (void *) NULL ? MagickTrue : MagickFalse;
769 if (segment == (void *) NULL)
770 segment=(void *) memory_methods.acquire_memory_handler(blocksize);
771 if (segment == (void *) NULL)
773 segment_info=(DataSegmentInfo *) free_segments;
774 free_segments=segment_info->next;
775 segment_info->mapped=mapped;
776 segment_info->length=blocksize;
777 segment_info->allocation=segment;
778 segment_info->bound=(char *) segment+blocksize;
779 i=(ssize_t) memory_pool.number_segments-1;
780 for ( ; (i >= 0) && (memory_pool.segments[i]->allocation > segment); i--)
781 memory_pool.segments[i+1]=memory_pool.segments[i];
782 memory_pool.segments[i+1]=segment_info;
783 memory_pool.number_segments++;
784 size=blocksize-12*sizeof(size_t);
785 block=(char *) segment_info->allocation+4*sizeof(size_t);
786 *BlockHeader(block)=size | PreviousBlockBit;
787 *BlockFooter(block,size)=size;
788 InsertFreeBlock(block,AllocationPolicy(size));
789 block=NextBlock(block);
790 assert(block < segment_info->bound);
791 *BlockHeader(block)=2*sizeof(size_t);
792 *BlockHeader(NextBlock(block))=PreviousBlockBit;
798 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
802 % G e t M a g i c k M e m o r y M e t h o d s %
806 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
808 % GetMagickMemoryMethods() gets the methods to acquire, resize, and destroy
811 % The format of the GetMagickMemoryMethods() method is:
813 % void GetMagickMemoryMethods(AcquireMemoryHandler *acquire_memory_handler,
814 % ResizeMemoryHandler *resize_memory_handler,
815 % DestroyMemoryHandler *destroy_memory_handler)
817 % A description of each parameter follows:
819 % o acquire_memory_handler: method to acquire memory (e.g. malloc).
821 % o resize_memory_handler: method to resize memory (e.g. realloc).
823 % o destroy_memory_handler: method to destroy memory (e.g. free).
826 MagickExport void GetMagickMemoryMethods(
827 AcquireMemoryHandler *acquire_memory_handler,
828 ResizeMemoryHandler *resize_memory_handler,
829 DestroyMemoryHandler *destroy_memory_handler)
831 assert(acquire_memory_handler != (AcquireMemoryHandler *) NULL);
832 assert(resize_memory_handler != (ResizeMemoryHandler *) NULL);
833 assert(destroy_memory_handler != (DestroyMemoryHandler *) NULL);
834 *acquire_memory_handler=memory_methods.acquire_memory_handler;
835 *resize_memory_handler=memory_methods.resize_memory_handler;
836 *destroy_memory_handler=memory_methods.destroy_memory_handler;
840 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
844 % G e t V i r t u a l M e m o r y B l o b %
848 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
850 % GetVirtualMemoryBlob() returns the virtual memory blob associated with the
851 % specified MemoryInfo structure.
853 % The format of the GetVirtualMemoryBlob method is:
855 % void *GetVirtualMemoryBlob(const MemoryInfo *memory_info)
857 % A description of each parameter follows:
859 % o memory_info: The MemoryInfo structure.
861 MagickExport void *GetVirtualMemoryBlob(const MemoryInfo *memory_info)
863 assert(memory_info != (const MemoryInfo *) NULL);
864 assert(memory_info->signature == MagickSignature);
865 return(memory_info->blob);
869 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
873 % R e l i n q u i s h A l i g n e d M e m o r y %
877 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
879 % RelinquishAlignedMemory() frees memory acquired with AcquireAlignedMemory()
882 % The format of the RelinquishAlignedMemory method is:
884 % void *RelinquishAlignedMemory(void *memory)
886 % A description of each parameter follows:
888 % o memory: A pointer to a block of memory to free for reuse.
891 MagickExport void *RelinquishAlignedMemory(void *memory)
893 if (memory == (void *) NULL)
894 return((void *) NULL);
895 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
897 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
898 _aligned_free(memory);
900 free(*((void **) memory-1));
906 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
910 % R e l i n q u i s h M a g i c k M e m o r y %
914 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
916 % RelinquishMagickMemory() frees memory acquired with AcquireMagickMemory()
917 % or AcquireQuantumMemory() for reuse.
919 % The format of the RelinquishMagickMemory method is:
921 % void *RelinquishMagickMemory(void *memory)
923 % A description of each parameter follows:
925 % o memory: A pointer to a block of memory to free for reuse.
928 MagickExport void *RelinquishMagickMemory(void *memory)
930 if (memory == (void *) NULL)
931 return((void *) NULL);
932 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
933 memory_methods.destroy_memory_handler(memory);
935 LockSemaphoreInfo(memory_semaphore);
936 assert((SizeOfBlock(memory) % (4*sizeof(size_t))) == 0);
937 assert((*BlockHeader(NextBlock(memory)) & PreviousBlockBit) != 0);
938 if ((*BlockHeader(memory) & PreviousBlockBit) == 0)
944 Coalesce with previous adjacent block.
946 previous=PreviousBlock(memory);
947 RemoveFreeBlock(previous,AllocationPolicy(SizeOfBlock(previous)));
948 *BlockHeader(previous)=(SizeOfBlock(previous)+SizeOfBlock(memory)) |
949 (*BlockHeader(previous) & ~SizeMask);
952 if ((*BlockHeader(NextBlock(NextBlock(memory))) & PreviousBlockBit) == 0)
958 Coalesce with next adjacent block.
960 next=NextBlock(memory);
961 RemoveFreeBlock(next,AllocationPolicy(SizeOfBlock(next)));
962 *BlockHeader(memory)=(SizeOfBlock(memory)+SizeOfBlock(next)) |
963 (*BlockHeader(memory) & ~SizeMask);
965 *BlockFooter(memory,SizeOfBlock(memory))=SizeOfBlock(memory);
966 *BlockHeader(NextBlock(memory))&=(~PreviousBlockBit);
967 InsertFreeBlock(memory,AllocationPolicy(SizeOfBlock(memory)));
968 UnlockSemaphoreInfo(memory_semaphore);
970 return((void *) NULL);
974 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
978 % R e l i n q u i s h V i r t u a l M e m o r y %
982 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
984 % RelinquishVirtualMemory() frees memory acquired with AcquireVirtualMemory().
986 % The format of the RelinquishVirtualMemory method is:
988 % MemoryInfo *RelinquishVirtualMemory(MemoryInfo *memory_info)
990 % A description of each parameter follows:
992 % o memory_info: A pointer to a block of memory to free for reuse.
995 MagickExport MemoryInfo *RelinquishVirtualMemory(MemoryInfo *memory_info)
997 assert(memory_info != (MemoryInfo *) NULL);
998 assert(memory_info->signature == MagickSignature);
999 if (memory_info->blob != (void *) NULL)
1000 switch (memory_info->type)
1002 case AlignedVirtualMemory:
1004 memory_info->blob=RelinquishAlignedMemory(memory_info->blob);
1005 RelinquishMagickResource(MemoryResource,memory_info->length);
1008 case MapVirtualMemory:
1010 (void) UnmapBlob(memory_info->blob,memory_info->length);
1011 memory_info->blob=NULL;
1012 RelinquishMagickResource(MapResource,memory_info->length);
1013 if (*memory_info->filename != '\0')
1014 (void) RelinquishUniqueFileResource(memory_info->filename);
1017 case UnalignedVirtualMemory:
1020 memory_info->blob=RelinquishMagickMemory(memory_info->blob);
1024 memory_info->signature=(~MagickSignature);
1025 memory_info=(MemoryInfo *) RelinquishAlignedMemory(memory_info);
1026 return(memory_info);
1030 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1034 % R e s e t M a g i c k M e m o r y %
1038 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1040 % ResetMagickMemory() fills the first size bytes of the memory area pointed to
1041 % by memory with the constant byte c.
1043 % The format of the ResetMagickMemory method is:
1045 % void *ResetMagickMemory(void *memory,int byte,const size_t size)
1047 % A description of each parameter follows:
1049 % o memory: a pointer to a memory allocation.
1051 % o byte: set the memory to this value.
1053 % o size: size of the memory to reset.
1056 MagickExport void *ResetMagickMemory(void *memory,int byte,const size_t size)
1058 assert(memory != (void *) NULL);
1059 return(memset(memory,byte,size));
1063 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1067 % R e s i z e M a g i c k M e m o r y %
1071 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1073 % ResizeMagickMemory() changes the size of the memory and returns a pointer to
1074 % the (possibly moved) block. The contents will be unchanged up to the
1075 % lesser of the new and old sizes.
1077 % The format of the ResizeMagickMemory method is:
1079 % void *ResizeMagickMemory(void *memory,const size_t size)
1081 % A description of each parameter follows:
1083 % o memory: A pointer to a memory allocation.
1085 % o size: the new size of the allocated memory.
1089 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
1090 static inline void *ResizeBlock(void *block,size_t size)
1095 if (block == (void *) NULL)
1096 return(AcquireBlock(size));
1097 memory=AcquireBlock(size);
1098 if (memory == (void *) NULL)
1099 return((void *) NULL);
1100 if (size <= (SizeOfBlock(block)-sizeof(size_t)))
1101 (void) memcpy(memory,block,size);
1103 (void) memcpy(memory,block,SizeOfBlock(block)-sizeof(size_t));
1104 memory_pool.allocation+=size;
1109 MagickExport void *ResizeMagickMemory(void *memory,const size_t size)
1114 if (memory == (void *) NULL)
1115 return(AcquireMagickMemory(size));
1116 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
1117 block=memory_methods.resize_memory_handler(memory,size == 0 ? 1UL : size);
1118 if (block == (void *) NULL)
1119 memory=RelinquishMagickMemory(memory);
1121 LockSemaphoreInfo(memory_semaphore);
1122 block=ResizeBlock(memory,size == 0 ? 1UL : size);
1123 if (block == (void *) NULL)
1125 if (ExpandHeap(size == 0 ? 1UL : size) == MagickFalse)
1127 UnlockSemaphoreInfo(memory_semaphore);
1128 memory=RelinquishMagickMemory(memory);
1129 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1131 block=ResizeBlock(memory,size == 0 ? 1UL : size);
1132 assert(block != (void *) NULL);
1134 UnlockSemaphoreInfo(memory_semaphore);
1135 memory=RelinquishMagickMemory(memory);
1141 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1145 % R e s i z e Q u a n t u m M e m o r y %
1149 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1151 % ResizeQuantumMemory() changes the size of the memory and returns a pointer
1152 % to the (possibly moved) block. The contents will be unchanged up to the
1153 % lesser of the new and old sizes.
1155 % The format of the ResizeQuantumMemory method is:
1157 % void *ResizeQuantumMemory(void *memory,const size_t count,
1158 % const size_t quantum)
1160 % A description of each parameter follows:
1162 % o memory: A pointer to a memory allocation.
1164 % o count: the number of quantum elements to allocate.
1166 % o quantum: the number of bytes in each quantum.
1169 MagickExport void *ResizeQuantumMemory(void *memory,const size_t count,
1170 const size_t quantum)
1176 if ((count == 0) || (quantum != (size/count)))
1178 memory=RelinquishMagickMemory(memory);
1180 return((void *) NULL);
1182 return(ResizeMagickMemory(memory,size));
1186 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1190 % S e t M a g i c k M e m o r y M e t h o d s %
1194 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1196 % SetMagickMemoryMethods() sets the methods to acquire, resize, and destroy
1197 % memory. Your custom memory methods must be set prior to the
1198 % MagickCoreGenesis() method.
1200 % The format of the SetMagickMemoryMethods() method is:
1202 % SetMagickMemoryMethods(AcquireMemoryHandler acquire_memory_handler,
1203 % ResizeMemoryHandler resize_memory_handler,
1204 % DestroyMemoryHandler destroy_memory_handler)
1206 % A description of each parameter follows:
1208 % o acquire_memory_handler: method to acquire memory (e.g. malloc).
1210 % o resize_memory_handler: method to resize memory (e.g. realloc).
1212 % o destroy_memory_handler: method to destroy memory (e.g. free).
1215 MagickExport void SetMagickMemoryMethods(
1216 AcquireMemoryHandler acquire_memory_handler,
1217 ResizeMemoryHandler resize_memory_handler,
1218 DestroyMemoryHandler destroy_memory_handler)
1223 if (acquire_memory_handler != (AcquireMemoryHandler) NULL)
1224 memory_methods.acquire_memory_handler=acquire_memory_handler;
1225 if (resize_memory_handler != (ResizeMemoryHandler) NULL)
1226 memory_methods.resize_memory_handler=resize_memory_handler;
1227 if (destroy_memory_handler != (DestroyMemoryHandler) NULL)
1228 memory_methods.destroy_memory_handler=destroy_memory_handler;