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-2012 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/semaphore.h"
64 #include "MagickCore/string_.h"
69 #define BlockFooter(block,size) \
70 ((size_t *) ((char *) (block)+(size)-2*sizeof(size_t)))
71 #define BlockHeader(block) ((size_t *) (block)-1)
72 #define BlockSize 4096
73 #define BlockThreshold 1024
74 #define MaxBlockExponent 16
75 #define MaxBlocks ((BlockThreshold/(4*sizeof(size_t)))+MaxBlockExponent+1)
76 #define MaxSegments 1024
77 #define MemoryGuard ((0xdeadbeef << 31)+0xdeafdeed)
78 #define NextBlock(block) ((char *) (block)+SizeOfBlock(block))
79 #define NextBlockInList(block) (*(void **) (block))
80 #define PreviousBlock(block) ((char *) (block)-(*((size_t *) (block)-2)))
81 #define PreviousBlockBit 0x01
82 #define PreviousBlockInList(block) (*((void **) (block)+1))
83 #define SegmentSize (2*1024*1024)
84 #define SizeMask (~0x01)
85 #define SizeOfBlock(block) (*BlockHeader(block) & SizeMask)
90 typedef struct _DataSegmentInfo
102 struct _DataSegmentInfo
107 typedef struct _MemoryInfo
113 *blocks[MaxBlocks+1];
119 *segments[MaxSegments],
120 segment_pool[MaxSegments];
123 typedef struct _MagickMemoryMethods
126 acquire_memory_handler;
129 resize_memory_handler;
132 destroy_memory_handler;
133 } MagickMemoryMethods;
139 static MagickMemoryMethods
142 (AcquireMemoryHandler) malloc,
143 (ResizeMemoryHandler) realloc,
144 (DestroyMemoryHandler) free
147 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
152 *memory_semaphore = (SemaphoreInfo *) NULL;
154 static volatile DataSegmentInfo
155 *free_segments = (DataSegmentInfo *) NULL;
158 Forward declarations.
160 static MagickBooleanType
165 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
169 % A c q u i r e A l i g n e d M e m o r y %
173 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
175 % AcquireAlignedMemory() returns a pointer to a block of memory at least size
176 % bytes whose address is a multiple of 16*sizeof(void *).
178 % The format of the AcquireAlignedMemory method is:
180 % void *AcquireAlignedMemory(const size_t count,const size_t quantum)
182 % A description of each parameter follows:
184 % o count: the number of quantum elements to allocate.
186 % o quantum: the number of bytes in each quantum.
189 MagickExport void *AcquireAlignedMemory(const size_t count,const size_t quantum)
191 #define AlignedExtent(size,alignment) \
192 (((size)+((alignment)-1)) & ~((alignment)-1))
203 if ((count == 0) || (quantum != (size/count)))
206 return((void *) NULL);
209 alignment=CACHE_LINE_SIZE;
210 extent=AlignedExtent(size,alignment);
211 if ((size == 0) || (alignment < sizeof(void *)) || (extent < size))
212 return((void *) NULL);
213 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
214 if (posix_memalign(&memory,alignment,extent) != 0)
216 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
217 memory=_aligned_malloc(extent,alignment);
223 extent=(size+alignment-1)+sizeof(void *);
229 memory=(void *) AlignedExtent((size_t) p+sizeof(void *),alignment);
230 *((void **) memory-1)=p;
238 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
240 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
244 + A c q u i r e B l o c k %
248 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
250 % AcquireBlock() returns a pointer to a block of memory at least size bytes
251 % suitably aligned for any use.
253 % The format of the AcquireBlock method is:
255 % void *AcquireBlock(const size_t size)
257 % A description of each parameter follows:
259 % o size: the size of the memory in bytes to allocate.
263 static inline size_t AllocationPolicy(size_t size)
269 The linear distribution.
272 assert(size % (4*sizeof(size_t)) == 0);
273 if (size <= BlockThreshold)
274 return(size/(4*sizeof(size_t)));
276 Check for the largest block size.
278 if (size > (size_t) (BlockThreshold*(1L << (MaxBlockExponent-1L))))
279 return(MaxBlocks-1L);
281 Otherwise use a power of two distribution.
283 blocksize=BlockThreshold/(4*sizeof(size_t));
284 for ( ; size > BlockThreshold; size/=2)
286 assert(blocksize > (BlockThreshold/(4*sizeof(size_t))));
287 assert(blocksize < (MaxBlocks-1L));
291 static inline void InsertFreeBlock(void *block,const size_t i)
300 size=SizeOfBlock(block);
301 previous=(void *) NULL;
302 next=memory_info.blocks[i];
303 while ((next != (void *) NULL) && (SizeOfBlock(next) < size))
306 next=NextBlockInList(next);
308 PreviousBlockInList(block)=previous;
309 NextBlockInList(block)=next;
310 if (previous != (void *) NULL)
311 NextBlockInList(previous)=block;
313 memory_info.blocks[i]=block;
314 if (next != (void *) NULL)
315 PreviousBlockInList(next)=block;
318 static inline void RemoveFreeBlock(void *block,const size_t i)
324 next=NextBlockInList(block);
325 previous=PreviousBlockInList(block);
326 if (previous == (void *) NULL)
327 memory_info.blocks[i]=next;
329 NextBlockInList(previous)=next;
330 if (next != (void *) NULL)
331 PreviousBlockInList(next)=previous;
334 static void *AcquireBlock(size_t size)
345 size=(size_t) (size+sizeof(size_t)+6*sizeof(size_t)-1) & -(4U*sizeof(size_t));
346 i=AllocationPolicy(size);
347 block=memory_info.blocks[i];
348 while ((block != (void *) NULL) && (SizeOfBlock(block) < size))
349 block=NextBlockInList(block);
350 if (block == (void *) NULL)
353 while (memory_info.blocks[i] == (void *) NULL)
355 block=memory_info.blocks[i];
357 return((void *) NULL);
359 assert((*BlockHeader(NextBlock(block)) & PreviousBlockBit) == 0);
360 assert(SizeOfBlock(block) >= size);
361 RemoveFreeBlock(block,AllocationPolicy(SizeOfBlock(block)));
362 if (SizeOfBlock(block) > size)
373 next=(char *) block+size;
374 blocksize=SizeOfBlock(block)-size;
375 *BlockHeader(next)=blocksize;
376 *BlockFooter(next,blocksize)=blocksize;
377 InsertFreeBlock(next,AllocationPolicy(blocksize));
378 *BlockHeader(block)=size | (*BlockHeader(block) & ~SizeMask);
380 assert(size == SizeOfBlock(block));
381 *BlockHeader(NextBlock(block))|=PreviousBlockBit;
382 memory_info.allocation+=size;
388 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
392 % A c q u i r e M a g i c k M e m o r y %
396 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
398 % AcquireMagickMemory() returns a pointer to a block of memory at least size
399 % bytes suitably aligned for any use.
401 % The format of the AcquireMagickMemory method is:
403 % void *AcquireMagickMemory(const size_t size)
405 % A description of each parameter follows:
407 % o size: the size of the memory in bytes to allocate.
410 MagickExport void *AcquireMagickMemory(const size_t size)
415 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
416 memory=memory_methods.acquire_memory_handler(size == 0 ? 1UL : size);
418 if (memory_semaphore == (SemaphoreInfo *) NULL)
419 AcquireSemaphoreInfo(&memory_semaphore);
420 if (free_segments == (DataSegmentInfo *) NULL)
422 LockSemaphoreInfo(memory_semaphore);
423 if (free_segments == (DataSegmentInfo *) NULL)
428 assert(2*sizeof(size_t) > (size_t) (~SizeMask));
429 (void) ResetMagickMemory(&memory_info,0,sizeof(memory_info));
430 memory_info.allocation=SegmentSize;
431 memory_info.blocks[MaxBlocks]=(void *) (-1);
432 for (i=0; i < MaxSegments; i++)
435 memory_info.segment_pool[i].previous=
436 (&memory_info.segment_pool[i-1]);
437 if (i != (MaxSegments-1))
438 memory_info.segment_pool[i].next=(&memory_info.segment_pool[i+1]);
440 free_segments=(&memory_info.segment_pool[0]);
442 UnlockSemaphoreInfo(memory_semaphore);
444 LockSemaphoreInfo(memory_semaphore);
445 memory=AcquireBlock(size == 0 ? 1UL : size);
446 if (memory == (void *) NULL)
448 if (ExpandHeap(size == 0 ? 1UL : size) != MagickFalse)
449 memory=AcquireBlock(size == 0 ? 1UL : size);
451 UnlockSemaphoreInfo(memory_semaphore);
457 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
461 % A c q u i r e Q u a n t u m M e m o r y %
465 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
467 % AcquireQuantumMemory() returns a pointer to a block of memory at least
468 % count * quantum bytes suitably aligned for any use.
470 % The format of the AcquireQuantumMemory method is:
472 % void *AcquireQuantumMemory(const size_t count,const size_t quantum)
474 % A description of each parameter follows:
476 % o count: the number of quantum elements to allocate.
478 % o quantum: the number of bytes in each quantum.
481 MagickExport void *AcquireQuantumMemory(const size_t count,const size_t quantum)
487 if ((count == 0) || (quantum != (size/count)))
490 return((void *) NULL);
492 return(AcquireMagickMemory(size));
496 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
500 % C o p y M a g i c k M e m o r y %
504 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
506 % CopyMagickMemory() copies size bytes from memory area source to the
507 % destination. Copying between objects that overlap will take place
508 % correctly. It returns destination.
510 % The format of the CopyMagickMemory method is:
512 % void *CopyMagickMemory(void *destination,const void *source,
515 % A description of each parameter follows:
517 % o destination: the destination.
519 % o source: the source.
521 % o size: the size of the memory in bytes to allocate.
524 MagickExport void *CopyMagickMemory(void *destination,const void *source,
527 register const unsigned char
530 register unsigned char
533 assert(destination != (void *) NULL);
534 assert(source != (const void *) NULL);
535 p=(const unsigned char *) source;
536 q=(unsigned char *) destination;
537 if (((q+size) < p) || (q > (p+size)))
540 default: return(memcpy(destination,source,size));
549 case 0: return(destination);
551 return(memmove(destination,source,size));
555 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
559 + D e s t r o y M a g i c k M e m o r y %
563 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
565 % DestroyMagickMemory() deallocates memory associated with the memory manager.
567 % The format of the DestroyMagickMemory method is:
569 % DestroyMagickMemory(void)
572 MagickExport void DestroyMagickMemory(void)
574 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
578 if (memory_semaphore == (SemaphoreInfo *) NULL)
579 AcquireSemaphoreInfo(&memory_semaphore);
580 LockSemaphoreInfo(memory_semaphore);
581 UnlockSemaphoreInfo(memory_semaphore);
582 for (i=0; i < (ssize_t) memory_info.number_segments; i++)
583 if (memory_info.segments[i]->mapped == MagickFalse)
584 memory_methods.destroy_memory_handler(
585 memory_info.segments[i]->allocation);
587 (void) UnmapBlob(memory_info.segments[i]->allocation,
588 memory_info.segments[i]->length);
589 free_segments=(DataSegmentInfo *) NULL;
590 (void) ResetMagickMemory(&memory_info,0,sizeof(memory_info));
591 DestroySemaphoreInfo(&memory_semaphore);
595 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
597 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
601 + E x p a n d H e a p %
605 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
607 % ExpandHeap() get more memory from the system. It returns MagickTrue on
608 % success otherwise MagickFalse.
610 % The format of the ExpandHeap method is:
612 % MagickBooleanType ExpandHeap(size_t size)
614 % A description of each parameter follows:
616 % o size: the size of the memory in bytes we require.
619 static MagickBooleanType ExpandHeap(size_t size)
639 blocksize=((size+12*sizeof(size_t))+SegmentSize-1) & -SegmentSize;
640 assert(memory_info.number_segments < MaxSegments);
641 segment=MapBlob(-1,IOMode,0,blocksize);
642 mapped=segment != (void *) NULL ? MagickTrue : MagickFalse;
643 if (segment == (void *) NULL)
644 segment=(void *) memory_methods.acquire_memory_handler(blocksize);
645 if (segment == (void *) NULL)
647 segment_info=(DataSegmentInfo *) free_segments;
648 free_segments=segment_info->next;
649 segment_info->mapped=mapped;
650 segment_info->length=blocksize;
651 segment_info->allocation=segment;
652 segment_info->bound=(char *) segment+blocksize;
653 i=(ssize_t) memory_info.number_segments-1;
654 for ( ; (i >= 0) && (memory_info.segments[i]->allocation > segment); i--)
655 memory_info.segments[i+1]=memory_info.segments[i];
656 memory_info.segments[i+1]=segment_info;
657 memory_info.number_segments++;
658 size=blocksize-12*sizeof(size_t);
659 block=(char *) segment_info->allocation+4*sizeof(size_t);
660 *BlockHeader(block)=size | PreviousBlockBit;
661 *BlockFooter(block,size)=size;
662 InsertFreeBlock(block,AllocationPolicy(size));
663 block=NextBlock(block);
664 assert(block < segment_info->bound);
665 *BlockHeader(block)=2*sizeof(size_t);
666 *BlockHeader(NextBlock(block))=PreviousBlockBit;
672 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
676 % G e t M a g i c k M e m o r y M e t h o d s %
680 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
682 % GetMagickMemoryMethods() gets the methods to acquire, resize, and destroy
685 % The format of the GetMagickMemoryMethods() method is:
687 % void GetMagickMemoryMethods(AcquireMemoryHandler *acquire_memory_handler,
688 % ResizeMemoryHandler *resize_memory_handler,
689 % DestroyMemoryHandler *destroy_memory_handler)
691 % A description of each parameter follows:
693 % o acquire_memory_handler: method to acquire memory (e.g. malloc).
695 % o resize_memory_handler: method to resize memory (e.g. realloc).
697 % o destroy_memory_handler: method to destroy memory (e.g. free).
700 MagickExport void GetMagickMemoryMethods(
701 AcquireMemoryHandler *acquire_memory_handler,
702 ResizeMemoryHandler *resize_memory_handler,
703 DestroyMemoryHandler *destroy_memory_handler)
705 assert(acquire_memory_handler != (AcquireMemoryHandler *) NULL);
706 assert(resize_memory_handler != (ResizeMemoryHandler *) NULL);
707 assert(destroy_memory_handler != (DestroyMemoryHandler *) NULL);
708 *acquire_memory_handler=memory_methods.acquire_memory_handler;
709 *resize_memory_handler=memory_methods.resize_memory_handler;
710 *destroy_memory_handler=memory_methods.destroy_memory_handler;
714 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
718 % R e l i n q u i s h A l i g n e d M e m o r y %
722 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
724 % RelinquishAlignedMemory() frees memory acquired with AcquireAlignedMemory()
727 % The format of the RelinquishAlignedMemory method is:
729 % void *RelinquishAlignedMemory(void *memory)
731 % A description of each parameter follows:
733 % o memory: A pointer to a block of memory to free for reuse.
736 MagickExport void *RelinquishAlignedMemory(void *memory)
738 if (memory == (void *) NULL)
739 return((void *) NULL);
740 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
742 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
743 _aligned_free(memory);
745 free(*((void **) memory-1));
751 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
755 % R e l i n q u i s h M a g i c k M e m o r y %
759 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
761 % RelinquishMagickMemory() frees memory acquired with AcquireMagickMemory()
762 % or AcquireQuantumMemory() for reuse.
764 % The format of the RelinquishMagickMemory method is:
766 % void *RelinquishMagickMemory(void *memory)
768 % A description of each parameter follows:
770 % o memory: A pointer to a block of memory to free for reuse.
773 MagickExport void *RelinquishMagickMemory(void *memory)
775 if (memory == (void *) NULL)
776 return((void *) NULL);
777 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
778 memory_methods.destroy_memory_handler(memory);
780 LockSemaphoreInfo(memory_semaphore);
781 assert((SizeOfBlock(memory) % (4*sizeof(size_t))) == 0);
782 assert((*BlockHeader(NextBlock(memory)) & PreviousBlockBit) != 0);
783 if ((*BlockHeader(memory) & PreviousBlockBit) == 0)
789 Coalesce with previous adjacent block.
791 previous=PreviousBlock(memory);
792 RemoveFreeBlock(previous,AllocationPolicy(SizeOfBlock(previous)));
793 *BlockHeader(previous)=(SizeOfBlock(previous)+SizeOfBlock(memory)) |
794 (*BlockHeader(previous) & ~SizeMask);
797 if ((*BlockHeader(NextBlock(NextBlock(memory))) & PreviousBlockBit) == 0)
803 Coalesce with next adjacent block.
805 next=NextBlock(memory);
806 RemoveFreeBlock(next,AllocationPolicy(SizeOfBlock(next)));
807 *BlockHeader(memory)=(SizeOfBlock(memory)+SizeOfBlock(next)) |
808 (*BlockHeader(memory) & ~SizeMask);
810 *BlockFooter(memory,SizeOfBlock(memory))=SizeOfBlock(memory);
811 *BlockHeader(NextBlock(memory))&=(~PreviousBlockBit);
812 InsertFreeBlock(memory,AllocationPolicy(SizeOfBlock(memory)));
813 UnlockSemaphoreInfo(memory_semaphore);
815 return((void *) NULL);
819 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
823 % R e s e t M a g i c k M e m o r y %
827 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
829 % ResetMagickMemory() fills the first size bytes of the memory area pointed to
830 % by memory with the constant byte c.
832 % The format of the ResetMagickMemory method is:
834 % void *ResetMagickMemory(void *memory,int byte,const size_t size)
836 % A description of each parameter follows:
838 % o memory: A pointer to a memory allocation.
840 % o byte: Set the memory to this value.
842 % o size: Size of the memory to reset.
845 MagickExport void *ResetMagickMemory(void *memory,int byte,const size_t size)
847 assert(memory != (void *) NULL);
848 return(memset(memory,byte,size));
852 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
856 % R e s i z e M a g i c k M e m o r y %
860 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
862 % ResizeMagickMemory() changes the size of the memory and returns a pointer to
863 % the (possibly moved) block. The contents will be unchanged up to the
864 % lesser of the new and old sizes.
866 % The format of the ResizeMagickMemory method is:
868 % void *ResizeMagickMemory(void *memory,const size_t size)
870 % A description of each parameter follows:
872 % o memory: A pointer to a memory allocation.
874 % o size: the new size of the allocated memory.
878 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
879 static inline void *ResizeBlock(void *block,size_t size)
884 if (block == (void *) NULL)
885 return(AcquireBlock(size));
886 memory=AcquireBlock(size);
887 if (memory == (void *) NULL)
888 return((void *) NULL);
889 if (size <= (SizeOfBlock(block)-sizeof(size_t)))
890 (void) memcpy(memory,block,size);
892 (void) memcpy(memory,block,SizeOfBlock(block)-sizeof(size_t));
893 memory_info.allocation+=size;
898 MagickExport void *ResizeMagickMemory(void *memory,const size_t size)
903 if (memory == (void *) NULL)
904 return(AcquireMagickMemory(size));
905 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
906 block=memory_methods.resize_memory_handler(memory,size == 0 ? 1UL : size);
907 if (block == (void *) NULL)
908 memory=RelinquishMagickMemory(memory);
910 LockSemaphoreInfo(memory_semaphore);
911 block=ResizeBlock(memory,size == 0 ? 1UL : size);
912 if (block == (void *) NULL)
914 if (ExpandHeap(size == 0 ? 1UL : size) == MagickFalse)
916 UnlockSemaphoreInfo(memory_semaphore);
917 memory=RelinquishMagickMemory(memory);
918 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
920 block=ResizeBlock(memory,size == 0 ? 1UL : size);
921 assert(block != (void *) NULL);
923 UnlockSemaphoreInfo(memory_semaphore);
924 memory=RelinquishMagickMemory(memory);
930 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
934 % R e s i z e Q u a n t u m M e m o r y %
938 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
940 % ResizeQuantumMemory() changes the size of the memory and returns a pointer
941 % to the (possibly moved) block. The contents will be unchanged up to the
942 % lesser of the new and old sizes.
944 % The format of the ResizeQuantumMemory method is:
946 % void *ResizeQuantumMemory(void *memory,const size_t count,
947 % const size_t quantum)
949 % A description of each parameter follows:
951 % o memory: A pointer to a memory allocation.
953 % o count: the number of quantum elements to allocate.
955 % o quantum: the number of bytes in each quantum.
958 MagickExport void *ResizeQuantumMemory(void *memory,const size_t count,
959 const size_t quantum)
965 if ((count == 0) || (quantum != (size/count)))
967 memory=RelinquishMagickMemory(memory);
969 return((void *) NULL);
971 return(ResizeMagickMemory(memory,size));
975 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
979 % S e t M a g i c k M e m o r y M e t h o d s %
983 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
985 % SetMagickMemoryMethods() sets the methods to acquire, resize, and destroy
988 % The format of the SetMagickMemoryMethods() method is:
990 % SetMagickMemoryMethods(AcquireMemoryHandler acquire_memory_handler,
991 % ResizeMemoryHandler resize_memory_handler,
992 % DestroyMemoryHandler destroy_memory_handler)
994 % A description of each parameter follows:
996 % o acquire_memory_handler: method to acquire memory (e.g. malloc).
998 % o resize_memory_handler: method to resize memory (e.g. realloc).
1000 % o destroy_memory_handler: method to destroy memory (e.g. free).
1003 MagickExport void SetMagickMemoryMethods(
1004 AcquireMemoryHandler acquire_memory_handler,
1005 ResizeMemoryHandler resize_memory_handler,
1006 DestroyMemoryHandler destroy_memory_handler)
1011 if (acquire_memory_handler != (AcquireMemoryHandler) NULL)
1012 memory_methods.acquire_memory_handler=acquire_memory_handler;
1013 if (resize_memory_handler != (ResizeMemoryHandler) NULL)
1014 memory_methods.resize_memory_handler=resize_memory_handler;
1015 if (destroy_memory_handler != (DestroyMemoryHandler) NULL)
1016 memory_methods.destroy_memory_handler=destroy_memory_handler;