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/semaphore.h"
63 #include "MagickCore/string_.h"
68 #define BlockFooter(block,size) \
69 ((size_t *) ((char *) (block)+(size)-2*sizeof(size_t)))
70 #define BlockHeader(block) ((size_t *) (block)-1)
71 #define BlockSize 4096
72 #define BlockThreshold 1024
73 #define AlignedSize (16*sizeof(void *))
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.
190 static inline size_t MagickMax(const size_t x,const size_t y)
197 MagickExport void *AcquireAlignedMemory(const size_t count,const size_t quantum)
203 if ((count == 0) || (quantum != (size/count)))
206 return((void *) NULL);
208 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
213 if (posix_memalign(&memory,AlignedSize,MagickMax(size,AlignedSize)) == 0)
217 return(malloc(MagickMax(size,AlignedSize)));
220 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
222 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
226 + A c q u i r e B l o c k %
230 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
232 % AcquireBlock() returns a pointer to a block of memory at least size bytes
233 % suitably aligned for any use.
235 % The format of the AcquireBlock method is:
237 % void *AcquireBlock(const size_t size)
239 % A description of each parameter follows:
241 % o size: the size of the memory in bytes to allocate.
245 static inline size_t AllocationPolicy(size_t size)
251 The linear distribution.
254 assert(size % (4*sizeof(size_t)) == 0);
255 if (size <= BlockThreshold)
256 return(size/(4*sizeof(size_t)));
258 Check for the largest block size.
260 if (size > (size_t) (BlockThreshold*(1L << (MaxBlockExponent-1L))))
261 return(MaxBlocks-1L);
263 Otherwise use a power of two distribution.
265 blocksize=BlockThreshold/(4*sizeof(size_t));
266 for ( ; size > BlockThreshold; size/=2)
268 assert(blocksize > (BlockThreshold/(4*sizeof(size_t))));
269 assert(blocksize < (MaxBlocks-1L));
273 static inline void InsertFreeBlock(void *block,const size_t i)
282 size=SizeOfBlock(block);
283 previous=(void *) NULL;
284 next=memory_info.blocks[i];
285 while ((next != (void *) NULL) && (SizeOfBlock(next) < size))
288 next=NextBlockInList(next);
290 PreviousBlockInList(block)=previous;
291 NextBlockInList(block)=next;
292 if (previous != (void *) NULL)
293 NextBlockInList(previous)=block;
295 memory_info.blocks[i]=block;
296 if (next != (void *) NULL)
297 PreviousBlockInList(next)=block;
300 static inline void RemoveFreeBlock(void *block,const size_t i)
306 next=NextBlockInList(block);
307 previous=PreviousBlockInList(block);
308 if (previous == (void *) NULL)
309 memory_info.blocks[i]=next;
311 NextBlockInList(previous)=next;
312 if (next != (void *) NULL)
313 PreviousBlockInList(next)=previous;
316 static void *AcquireBlock(size_t size)
327 size=(size_t) (size+sizeof(size_t)+6*sizeof(size_t)-1) & -(4U*sizeof(size_t));
328 i=AllocationPolicy(size);
329 block=memory_info.blocks[i];
330 while ((block != (void *) NULL) && (SizeOfBlock(block) < size))
331 block=NextBlockInList(block);
332 if (block == (void *) NULL)
335 while (memory_info.blocks[i] == (void *) NULL)
337 block=memory_info.blocks[i];
339 return((void *) NULL);
341 assert((*BlockHeader(NextBlock(block)) & PreviousBlockBit) == 0);
342 assert(SizeOfBlock(block) >= size);
343 RemoveFreeBlock(block,AllocationPolicy(SizeOfBlock(block)));
344 if (SizeOfBlock(block) > size)
355 next=(char *) block+size;
356 blocksize=SizeOfBlock(block)-size;
357 *BlockHeader(next)=blocksize;
358 *BlockFooter(next,blocksize)=blocksize;
359 InsertFreeBlock(next,AllocationPolicy(blocksize));
360 *BlockHeader(block)=size | (*BlockHeader(block) & ~SizeMask);
362 assert(size == SizeOfBlock(block));
363 *BlockHeader(NextBlock(block))|=PreviousBlockBit;
364 memory_info.allocation+=size;
370 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
374 % A c q u i r e M a g i c k M e m o r y %
378 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
380 % AcquireMagickMemory() returns a pointer to a block of memory at least size
381 % bytes suitably aligned for any use.
383 % The format of the AcquireMagickMemory method is:
385 % void *AcquireMagickMemory(const size_t size)
387 % A description of each parameter follows:
389 % o size: the size of the memory in bytes to allocate.
392 MagickExport void *AcquireMagickMemory(const size_t size)
397 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
398 memory=memory_methods.acquire_memory_handler(size == 0 ? 1UL : size);
400 if (memory_semaphore == (SemaphoreInfo *) NULL)
401 AcquireSemaphoreInfo(&memory_semaphore);
402 if (free_segments == (DataSegmentInfo *) NULL)
404 LockSemaphoreInfo(memory_semaphore);
405 if (free_segments == (DataSegmentInfo *) NULL)
410 assert(2*sizeof(size_t) > (size_t) (~SizeMask));
411 (void) ResetMagickMemory(&memory_info,0,sizeof(memory_info));
412 memory_info.allocation=SegmentSize;
413 memory_info.blocks[MaxBlocks]=(void *) (-1);
414 for (i=0; i < MaxSegments; i++)
417 memory_info.segment_pool[i].previous=
418 (&memory_info.segment_pool[i-1]);
419 if (i != (MaxSegments-1))
420 memory_info.segment_pool[i].next=(&memory_info.segment_pool[i+1]);
422 free_segments=(&memory_info.segment_pool[0]);
424 UnlockSemaphoreInfo(memory_semaphore);
426 LockSemaphoreInfo(memory_semaphore);
427 memory=AcquireBlock(size == 0 ? 1UL : size);
428 if (memory == (void *) NULL)
430 if (ExpandHeap(size == 0 ? 1UL : size) != MagickFalse)
431 memory=AcquireBlock(size == 0 ? 1UL : size);
433 UnlockSemaphoreInfo(memory_semaphore);
439 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
443 % A c q u i r e Q u a n t u m M e m o r y %
447 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
449 % AcquireQuantumMemory() returns a pointer to a block of memory at least
450 % count * quantum bytes suitably aligned for any use.
452 % The format of the AcquireQuantumMemory method is:
454 % void *AcquireQuantumMemory(const size_t count,const size_t quantum)
456 % A description of each parameter follows:
458 % o count: the number of quantum elements to allocate.
460 % o quantum: the number of bytes in each quantum.
463 MagickExport void *AcquireQuantumMemory(const size_t count,const size_t quantum)
469 if ((count == 0) || (quantum != (size/count)))
472 return((void *) NULL);
474 return(AcquireMagickMemory(size));
478 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
482 % C o p y M a g i c k M e m o r y %
486 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
488 % CopyMagickMemory() copies size bytes from memory area source to the
489 % destination. Copying between objects that overlap will take place
490 % correctly. It returns destination.
492 % The format of the CopyMagickMemory method is:
494 % void *CopyMagickMemory(void *destination,const void *source,
497 % A description of each parameter follows:
499 % o destination: the destination.
501 % o source: the source.
503 % o size: the size of the memory in bytes to allocate.
506 MagickExport void *CopyMagickMemory(void *destination,const void *source,
509 register const unsigned char
512 register unsigned char
515 assert(destination != (void *) NULL);
516 assert(source != (const void *) NULL);
517 p=(const unsigned char *) source;
518 q=(unsigned char *) destination;
519 if (((q+size) < p) || (q > (p+size)))
522 default: return(memcpy(destination,source,size));
531 case 0: return(destination);
533 return(memmove(destination,source,size));
537 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
541 + D e s t r o y M a g i c k M e m o r y %
545 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
547 % DestroyMagickMemory() deallocates memory associated with the memory manager.
549 % The format of the DestroyMagickMemory method is:
551 % DestroyMagickMemory(void)
554 MagickExport void DestroyMagickMemory(void)
556 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
560 if (memory_semaphore == (SemaphoreInfo *) NULL)
561 AcquireSemaphoreInfo(&memory_semaphore);
562 LockSemaphoreInfo(memory_semaphore);
563 UnlockSemaphoreInfo(memory_semaphore);
564 for (i=0; i < (ssize_t) memory_info.number_segments; i++)
565 if (memory_info.segments[i]->mapped == MagickFalse)
566 memory_methods.destroy_memory_handler(
567 memory_info.segments[i]->allocation);
569 (void) UnmapBlob(memory_info.segments[i]->allocation,
570 memory_info.segments[i]->length);
571 free_segments=(DataSegmentInfo *) NULL;
572 (void) ResetMagickMemory(&memory_info,0,sizeof(memory_info));
573 DestroySemaphoreInfo(&memory_semaphore);
577 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
579 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
583 + E x p a n d H e a p %
587 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
589 % ExpandHeap() get more memory from the system. It returns MagickTrue on
590 % success otherwise MagickFalse.
592 % The format of the ExpandHeap method is:
594 % MagickBooleanType ExpandHeap(size_t size)
596 % A description of each parameter follows:
598 % o size: the size of the memory in bytes we require.
601 static MagickBooleanType ExpandHeap(size_t size)
621 blocksize=((size+12*sizeof(size_t))+SegmentSize-1) & -SegmentSize;
622 assert(memory_info.number_segments < MaxSegments);
623 segment=MapBlob(-1,IOMode,0,blocksize);
624 mapped=segment != (void *) NULL ? MagickTrue : MagickFalse;
625 if (segment == (void *) NULL)
626 segment=(void *) memory_methods.acquire_memory_handler(blocksize);
627 if (segment == (void *) NULL)
629 segment_info=(DataSegmentInfo *) free_segments;
630 free_segments=segment_info->next;
631 segment_info->mapped=mapped;
632 segment_info->length=blocksize;
633 segment_info->allocation=segment;
634 segment_info->bound=(char *) segment+blocksize;
635 i=(ssize_t) memory_info.number_segments-1;
636 for ( ; (i >= 0) && (memory_info.segments[i]->allocation > segment); i--)
637 memory_info.segments[i+1]=memory_info.segments[i];
638 memory_info.segments[i+1]=segment_info;
639 memory_info.number_segments++;
640 size=blocksize-12*sizeof(size_t);
641 block=(char *) segment_info->allocation+4*sizeof(size_t);
642 *BlockHeader(block)=size | PreviousBlockBit;
643 *BlockFooter(block,size)=size;
644 InsertFreeBlock(block,AllocationPolicy(size));
645 block=NextBlock(block);
646 assert(block < segment_info->bound);
647 *BlockHeader(block)=2*sizeof(size_t);
648 *BlockHeader(NextBlock(block))=PreviousBlockBit;
654 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
658 % G e t M a g i c k M e m o r y M e t h o d s %
662 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
664 % GetMagickMemoryMethods() gets the methods to acquire, resize, and destroy
667 % The format of the GetMagickMemoryMethods() method is:
669 % void GetMagickMemoryMethods(AcquireMemoryHandler *acquire_memory_handler,
670 % ResizeMemoryHandler *resize_memory_handler,
671 % DestroyMemoryHandler *destroy_memory_handler)
673 % A description of each parameter follows:
675 % o acquire_memory_handler: method to acquire memory (e.g. malloc).
677 % o resize_memory_handler: method to resize memory (e.g. realloc).
679 % o destroy_memory_handler: method to destroy memory (e.g. free).
682 MagickExport void GetMagickMemoryMethods(
683 AcquireMemoryHandler *acquire_memory_handler,
684 ResizeMemoryHandler *resize_memory_handler,
685 DestroyMemoryHandler *destroy_memory_handler)
687 assert(acquire_memory_handler != (AcquireMemoryHandler *) NULL);
688 assert(resize_memory_handler != (ResizeMemoryHandler *) NULL);
689 assert(destroy_memory_handler != (DestroyMemoryHandler *) NULL);
690 *acquire_memory_handler=memory_methods.acquire_memory_handler;
691 *resize_memory_handler=memory_methods.resize_memory_handler;
692 *destroy_memory_handler=memory_methods.destroy_memory_handler;
696 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
700 % R e l i n q u i s h A l i g n e d M e m o r y %
704 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
706 % RelinquishAlignedMemory() frees memory acquired with AcquireAlignedMemory()
709 % The format of the RelinquishAlignedMemory method is:
711 % void *RelinquishAlignedMemory(void *memory)
713 % A description of each parameter follows:
715 % o memory: A pointer to a block of memory to free for reuse.
718 MagickExport void *RelinquishAlignedMemory(void *memory)
720 if (memory == (void *) NULL)
721 return((void *) NULL);
723 return((void *) NULL);
727 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
731 % R e l i n q u i s h M a g i c k M e m o r y %
735 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
737 % RelinquishMagickMemory() frees memory acquired with AcquireMagickMemory()
738 % or AcquireQuantumMemory() for reuse.
740 % The format of the RelinquishMagickMemory method is:
742 % void *RelinquishMagickMemory(void *memory)
744 % A description of each parameter follows:
746 % o memory: A pointer to a block of memory to free for reuse.
749 MagickExport void *RelinquishMagickMemory(void *memory)
751 if (memory == (void *) NULL)
752 return((void *) NULL);
753 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
754 memory_methods.destroy_memory_handler(memory);
756 LockSemaphoreInfo(memory_semaphore);
757 assert((SizeOfBlock(memory) % (4*sizeof(size_t))) == 0);
758 assert((*BlockHeader(NextBlock(memory)) & PreviousBlockBit) != 0);
759 if ((*BlockHeader(memory) & PreviousBlockBit) == 0)
765 Coalesce with previous adjacent block.
767 previous=PreviousBlock(memory);
768 RemoveFreeBlock(previous,AllocationPolicy(SizeOfBlock(previous)));
769 *BlockHeader(previous)=(SizeOfBlock(previous)+SizeOfBlock(memory)) |
770 (*BlockHeader(previous) & ~SizeMask);
773 if ((*BlockHeader(NextBlock(NextBlock(memory))) & PreviousBlockBit) == 0)
779 Coalesce with next adjacent block.
781 next=NextBlock(memory);
782 RemoveFreeBlock(next,AllocationPolicy(SizeOfBlock(next)));
783 *BlockHeader(memory)=(SizeOfBlock(memory)+SizeOfBlock(next)) |
784 (*BlockHeader(memory) & ~SizeMask);
786 *BlockFooter(memory,SizeOfBlock(memory))=SizeOfBlock(memory);
787 *BlockHeader(NextBlock(memory))&=(~PreviousBlockBit);
788 InsertFreeBlock(memory,AllocationPolicy(SizeOfBlock(memory)));
789 UnlockSemaphoreInfo(memory_semaphore);
791 return((void *) NULL);
795 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
799 % R e s e t M a g i c k M e m o r y %
803 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
805 % ResetMagickMemory() fills the first size bytes of the memory area pointed to
806 % by memory with the constant byte c.
808 % The format of the ResetMagickMemory method is:
810 % void *ResetMagickMemory(void *memory,int byte,const size_t size)
812 % A description of each parameter follows:
814 % o memory: A pointer to a memory allocation.
816 % o byte: Set the memory to this value.
818 % o size: Size of the memory to reset.
821 MagickExport void *ResetMagickMemory(void *memory,int byte,const size_t size)
823 assert(memory != (void *) NULL);
824 return(memset(memory,byte,size));
828 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
832 % R e s i z e M a g i c k M e m o r y %
836 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
838 % ResizeMagickMemory() changes the size of the memory and returns a pointer to
839 % the (possibly moved) block. The contents will be unchanged up to the
840 % lesser of the new and old sizes.
842 % The format of the ResizeMagickMemory method is:
844 % void *ResizeMagickMemory(void *memory,const size_t size)
846 % A description of each parameter follows:
848 % o memory: A pointer to a memory allocation.
850 % o size: the new size of the allocated memory.
854 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
855 static inline void *ResizeBlock(void *block,size_t size)
860 if (block == (void *) NULL)
861 return(AcquireBlock(size));
862 memory=AcquireBlock(size);
863 if (memory == (void *) NULL)
864 return((void *) NULL);
865 if (size <= (SizeOfBlock(block)-sizeof(size_t)))
866 (void) memcpy(memory,block,size);
868 (void) memcpy(memory,block,SizeOfBlock(block)-sizeof(size_t));
869 memory_info.allocation+=size;
874 MagickExport void *ResizeMagickMemory(void *memory,const size_t size)
879 if (memory == (void *) NULL)
880 return(AcquireMagickMemory(size));
881 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
882 block=memory_methods.resize_memory_handler(memory,size == 0 ? 1UL : size);
883 if (block == (void *) NULL)
884 memory=RelinquishMagickMemory(memory);
886 LockSemaphoreInfo(memory_semaphore);
887 block=ResizeBlock(memory,size == 0 ? 1UL : size);
888 if (block == (void *) NULL)
890 if (ExpandHeap(size == 0 ? 1UL : size) == MagickFalse)
892 UnlockSemaphoreInfo(memory_semaphore);
893 memory=RelinquishMagickMemory(memory);
894 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
896 block=ResizeBlock(memory,size == 0 ? 1UL : size);
897 assert(block != (void *) NULL);
899 UnlockSemaphoreInfo(memory_semaphore);
900 memory=RelinquishMagickMemory(memory);
906 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
910 % R e s i z e Q u a n t u m M e m o r y %
914 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
916 % ResizeQuantumMemory() changes the size of the memory and returns a pointer
917 % to the (possibly moved) block. The contents will be unchanged up to the
918 % lesser of the new and old sizes.
920 % The format of the ResizeQuantumMemory method is:
922 % void *ResizeQuantumMemory(void *memory,const size_t count,
923 % const size_t quantum)
925 % A description of each parameter follows:
927 % o memory: A pointer to a memory allocation.
929 % o count: the number of quantum elements to allocate.
931 % o quantum: the number of bytes in each quantum.
934 MagickExport void *ResizeQuantumMemory(void *memory,const size_t count,
935 const size_t quantum)
941 if ((count == 0) || (quantum != (size/count)))
943 memory=RelinquishMagickMemory(memory);
945 return((void *) NULL);
947 return(ResizeMagickMemory(memory,size));
951 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
955 % S e t M a g i c k M e m o r y M e t h o d s %
959 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
961 % SetMagickMemoryMethods() sets the methods to acquire, resize, and destroy
964 % The format of the SetMagickMemoryMethods() method is:
966 % SetMagickMemoryMethods(AcquireMemoryHandler acquire_memory_handler,
967 % ResizeMemoryHandler resize_memory_handler,
968 % DestroyMemoryHandler destroy_memory_handler)
970 % A description of each parameter follows:
972 % o acquire_memory_handler: method to acquire memory (e.g. malloc).
974 % o resize_memory_handler: method to resize memory (e.g. realloc).
976 % o destroy_memory_handler: method to destroy memory (e.g. free).
979 MagickExport void SetMagickMemoryMethods(
980 AcquireMemoryHandler acquire_memory_handler,
981 ResizeMemoryHandler resize_memory_handler,
982 DestroyMemoryHandler destroy_memory_handler)
987 if (acquire_memory_handler != (AcquireMemoryHandler) NULL)
988 memory_methods.acquire_memory_handler=acquire_memory_handler;
989 if (resize_memory_handler != (ResizeMemoryHandler) NULL)
990 memory_methods.resize_memory_handler=resize_memory_handler;
991 if (destroy_memory_handler != (DestroyMemoryHandler) NULL)
992 memory_methods.destroy_memory_handler=destroy_memory_handler;