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)
195 if ((count == 0) || (quantum != (size/count)))
198 return((void *) NULL);
200 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
205 if (posix_memalign(&memory,CACHE_LINE_SIZE,CacheAlign(size)) == 0)
209 return(malloc(CacheAlign(size)));
212 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
214 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
218 + A c q u i r e B l o c k %
222 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
224 % AcquireBlock() returns a pointer to a block of memory at least size bytes
225 % suitably aligned for any use.
227 % The format of the AcquireBlock method is:
229 % void *AcquireBlock(const size_t size)
231 % A description of each parameter follows:
233 % o size: the size of the memory in bytes to allocate.
237 static inline size_t AllocationPolicy(size_t size)
243 The linear distribution.
246 assert(size % (4*sizeof(size_t)) == 0);
247 if (size <= BlockThreshold)
248 return(size/(4*sizeof(size_t)));
250 Check for the largest block size.
252 if (size > (size_t) (BlockThreshold*(1L << (MaxBlockExponent-1L))))
253 return(MaxBlocks-1L);
255 Otherwise use a power of two distribution.
257 blocksize=BlockThreshold/(4*sizeof(size_t));
258 for ( ; size > BlockThreshold; size/=2)
260 assert(blocksize > (BlockThreshold/(4*sizeof(size_t))));
261 assert(blocksize < (MaxBlocks-1L));
265 static inline void InsertFreeBlock(void *block,const size_t i)
274 size=SizeOfBlock(block);
275 previous=(void *) NULL;
276 next=memory_info.blocks[i];
277 while ((next != (void *) NULL) && (SizeOfBlock(next) < size))
280 next=NextBlockInList(next);
282 PreviousBlockInList(block)=previous;
283 NextBlockInList(block)=next;
284 if (previous != (void *) NULL)
285 NextBlockInList(previous)=block;
287 memory_info.blocks[i]=block;
288 if (next != (void *) NULL)
289 PreviousBlockInList(next)=block;
292 static inline void RemoveFreeBlock(void *block,const size_t i)
298 next=NextBlockInList(block);
299 previous=PreviousBlockInList(block);
300 if (previous == (void *) NULL)
301 memory_info.blocks[i]=next;
303 NextBlockInList(previous)=next;
304 if (next != (void *) NULL)
305 PreviousBlockInList(next)=previous;
308 static void *AcquireBlock(size_t size)
319 size=(size_t) (size+sizeof(size_t)+6*sizeof(size_t)-1) & -(4U*sizeof(size_t));
320 i=AllocationPolicy(size);
321 block=memory_info.blocks[i];
322 while ((block != (void *) NULL) && (SizeOfBlock(block) < size))
323 block=NextBlockInList(block);
324 if (block == (void *) NULL)
327 while (memory_info.blocks[i] == (void *) NULL)
329 block=memory_info.blocks[i];
331 return((void *) NULL);
333 assert((*BlockHeader(NextBlock(block)) & PreviousBlockBit) == 0);
334 assert(SizeOfBlock(block) >= size);
335 RemoveFreeBlock(block,AllocationPolicy(SizeOfBlock(block)));
336 if (SizeOfBlock(block) > size)
347 next=(char *) block+size;
348 blocksize=SizeOfBlock(block)-size;
349 *BlockHeader(next)=blocksize;
350 *BlockFooter(next,blocksize)=blocksize;
351 InsertFreeBlock(next,AllocationPolicy(blocksize));
352 *BlockHeader(block)=size | (*BlockHeader(block) & ~SizeMask);
354 assert(size == SizeOfBlock(block));
355 *BlockHeader(NextBlock(block))|=PreviousBlockBit;
356 memory_info.allocation+=size;
362 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
366 % A c q u i r e M a g i c k M e m o r y %
370 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
372 % AcquireMagickMemory() returns a pointer to a block of memory at least size
373 % bytes suitably aligned for any use.
375 % The format of the AcquireMagickMemory method is:
377 % void *AcquireMagickMemory(const size_t size)
379 % A description of each parameter follows:
381 % o size: the size of the memory in bytes to allocate.
384 MagickExport void *AcquireMagickMemory(const size_t size)
389 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
390 memory=memory_methods.acquire_memory_handler(size == 0 ? 1UL : size);
392 if (memory_semaphore == (SemaphoreInfo *) NULL)
393 AcquireSemaphoreInfo(&memory_semaphore);
394 if (free_segments == (DataSegmentInfo *) NULL)
396 LockSemaphoreInfo(memory_semaphore);
397 if (free_segments == (DataSegmentInfo *) NULL)
402 assert(2*sizeof(size_t) > (size_t) (~SizeMask));
403 (void) ResetMagickMemory(&memory_info,0,sizeof(memory_info));
404 memory_info.allocation=SegmentSize;
405 memory_info.blocks[MaxBlocks]=(void *) (-1);
406 for (i=0; i < MaxSegments; i++)
409 memory_info.segment_pool[i].previous=
410 (&memory_info.segment_pool[i-1]);
411 if (i != (MaxSegments-1))
412 memory_info.segment_pool[i].next=(&memory_info.segment_pool[i+1]);
414 free_segments=(&memory_info.segment_pool[0]);
416 UnlockSemaphoreInfo(memory_semaphore);
418 LockSemaphoreInfo(memory_semaphore);
419 memory=AcquireBlock(size == 0 ? 1UL : size);
420 if (memory == (void *) NULL)
422 if (ExpandHeap(size == 0 ? 1UL : size) != MagickFalse)
423 memory=AcquireBlock(size == 0 ? 1UL : size);
425 UnlockSemaphoreInfo(memory_semaphore);
431 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
435 % A c q u i r e Q u a n t u m M e m o r y %
439 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
441 % AcquireQuantumMemory() returns a pointer to a block of memory at least
442 % count * quantum bytes suitably aligned for any use.
444 % The format of the AcquireQuantumMemory method is:
446 % void *AcquireQuantumMemory(const size_t count,const size_t quantum)
448 % A description of each parameter follows:
450 % o count: the number of quantum elements to allocate.
452 % o quantum: the number of bytes in each quantum.
455 MagickExport void *AcquireQuantumMemory(const size_t count,const size_t quantum)
461 if ((count == 0) || (quantum != (size/count)))
464 return((void *) NULL);
466 return(AcquireMagickMemory(size));
470 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
474 % C o p y M a g i c k M e m o r y %
478 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
480 % CopyMagickMemory() copies size bytes from memory area source to the
481 % destination. Copying between objects that overlap will take place
482 % correctly. It returns destination.
484 % The format of the CopyMagickMemory method is:
486 % void *CopyMagickMemory(void *destination,const void *source,
489 % A description of each parameter follows:
491 % o destination: the destination.
493 % o source: the source.
495 % o size: the size of the memory in bytes to allocate.
498 MagickExport void *CopyMagickMemory(void *destination,const void *source,
501 register const unsigned char
504 register unsigned char
507 assert(destination != (void *) NULL);
508 assert(source != (const void *) NULL);
509 p=(const unsigned char *) source;
510 q=(unsigned char *) destination;
511 if (((q+size) < p) || (q > (p+size)))
514 default: return(memcpy(destination,source,size));
523 case 0: return(destination);
525 return(memmove(destination,source,size));
529 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
533 + D e s t r o y M a g i c k M e m o r y %
537 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
539 % DestroyMagickMemory() deallocates memory associated with the memory manager.
541 % The format of the DestroyMagickMemory method is:
543 % DestroyMagickMemory(void)
546 MagickExport void DestroyMagickMemory(void)
548 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
552 if (memory_semaphore == (SemaphoreInfo *) NULL)
553 AcquireSemaphoreInfo(&memory_semaphore);
554 LockSemaphoreInfo(memory_semaphore);
555 UnlockSemaphoreInfo(memory_semaphore);
556 for (i=0; i < (ssize_t) memory_info.number_segments; i++)
557 if (memory_info.segments[i]->mapped == MagickFalse)
558 memory_methods.destroy_memory_handler(
559 memory_info.segments[i]->allocation);
561 (void) UnmapBlob(memory_info.segments[i]->allocation,
562 memory_info.segments[i]->length);
563 free_segments=(DataSegmentInfo *) NULL;
564 (void) ResetMagickMemory(&memory_info,0,sizeof(memory_info));
565 DestroySemaphoreInfo(&memory_semaphore);
569 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
571 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
575 + E x p a n d H e a p %
579 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
581 % ExpandHeap() get more memory from the system. It returns MagickTrue on
582 % success otherwise MagickFalse.
584 % The format of the ExpandHeap method is:
586 % MagickBooleanType ExpandHeap(size_t size)
588 % A description of each parameter follows:
590 % o size: the size of the memory in bytes we require.
593 static MagickBooleanType ExpandHeap(size_t size)
613 blocksize=((size+12*sizeof(size_t))+SegmentSize-1) & -SegmentSize;
614 assert(memory_info.number_segments < MaxSegments);
615 segment=MapBlob(-1,IOMode,0,blocksize);
616 mapped=segment != (void *) NULL ? MagickTrue : MagickFalse;
617 if (segment == (void *) NULL)
618 segment=(void *) memory_methods.acquire_memory_handler(blocksize);
619 if (segment == (void *) NULL)
621 segment_info=(DataSegmentInfo *) free_segments;
622 free_segments=segment_info->next;
623 segment_info->mapped=mapped;
624 segment_info->length=blocksize;
625 segment_info->allocation=segment;
626 segment_info->bound=(char *) segment+blocksize;
627 i=(ssize_t) memory_info.number_segments-1;
628 for ( ; (i >= 0) && (memory_info.segments[i]->allocation > segment); i--)
629 memory_info.segments[i+1]=memory_info.segments[i];
630 memory_info.segments[i+1]=segment_info;
631 memory_info.number_segments++;
632 size=blocksize-12*sizeof(size_t);
633 block=(char *) segment_info->allocation+4*sizeof(size_t);
634 *BlockHeader(block)=size | PreviousBlockBit;
635 *BlockFooter(block,size)=size;
636 InsertFreeBlock(block,AllocationPolicy(size));
637 block=NextBlock(block);
638 assert(block < segment_info->bound);
639 *BlockHeader(block)=2*sizeof(size_t);
640 *BlockHeader(NextBlock(block))=PreviousBlockBit;
646 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
650 % G e t M a g i c k M e m o r y M e t h o d s %
654 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
656 % GetMagickMemoryMethods() gets the methods to acquire, resize, and destroy
659 % The format of the GetMagickMemoryMethods() method is:
661 % void GetMagickMemoryMethods(AcquireMemoryHandler *acquire_memory_handler,
662 % ResizeMemoryHandler *resize_memory_handler,
663 % DestroyMemoryHandler *destroy_memory_handler)
665 % A description of each parameter follows:
667 % o acquire_memory_handler: method to acquire memory (e.g. malloc).
669 % o resize_memory_handler: method to resize memory (e.g. realloc).
671 % o destroy_memory_handler: method to destroy memory (e.g. free).
674 MagickExport void GetMagickMemoryMethods(
675 AcquireMemoryHandler *acquire_memory_handler,
676 ResizeMemoryHandler *resize_memory_handler,
677 DestroyMemoryHandler *destroy_memory_handler)
679 assert(acquire_memory_handler != (AcquireMemoryHandler *) NULL);
680 assert(resize_memory_handler != (ResizeMemoryHandler *) NULL);
681 assert(destroy_memory_handler != (DestroyMemoryHandler *) NULL);
682 *acquire_memory_handler=memory_methods.acquire_memory_handler;
683 *resize_memory_handler=memory_methods.resize_memory_handler;
684 *destroy_memory_handler=memory_methods.destroy_memory_handler;
688 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
692 % R e l i n q u i s h A l i g n e d M e m o r y %
696 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
698 % RelinquishAlignedMemory() frees memory acquired with AcquireAlignedMemory()
701 % The format of the RelinquishAlignedMemory method is:
703 % void *RelinquishAlignedMemory(void *memory)
705 % A description of each parameter follows:
707 % o memory: A pointer to a block of memory to free for reuse.
710 MagickExport void *RelinquishAlignedMemory(void *memory)
712 if (memory == (void *) NULL)
713 return((void *) NULL);
715 return((void *) NULL);
719 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
723 % R e l i n q u i s h M a g i c k M e m o r y %
727 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
729 % RelinquishMagickMemory() frees memory acquired with AcquireMagickMemory()
730 % or AcquireQuantumMemory() for reuse.
732 % The format of the RelinquishMagickMemory method is:
734 % void *RelinquishMagickMemory(void *memory)
736 % A description of each parameter follows:
738 % o memory: A pointer to a block of memory to free for reuse.
741 MagickExport void *RelinquishMagickMemory(void *memory)
743 if (memory == (void *) NULL)
744 return((void *) NULL);
745 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
746 memory_methods.destroy_memory_handler(memory);
748 LockSemaphoreInfo(memory_semaphore);
749 assert((SizeOfBlock(memory) % (4*sizeof(size_t))) == 0);
750 assert((*BlockHeader(NextBlock(memory)) & PreviousBlockBit) != 0);
751 if ((*BlockHeader(memory) & PreviousBlockBit) == 0)
757 Coalesce with previous adjacent block.
759 previous=PreviousBlock(memory);
760 RemoveFreeBlock(previous,AllocationPolicy(SizeOfBlock(previous)));
761 *BlockHeader(previous)=(SizeOfBlock(previous)+SizeOfBlock(memory)) |
762 (*BlockHeader(previous) & ~SizeMask);
765 if ((*BlockHeader(NextBlock(NextBlock(memory))) & PreviousBlockBit) == 0)
771 Coalesce with next adjacent block.
773 next=NextBlock(memory);
774 RemoveFreeBlock(next,AllocationPolicy(SizeOfBlock(next)));
775 *BlockHeader(memory)=(SizeOfBlock(memory)+SizeOfBlock(next)) |
776 (*BlockHeader(memory) & ~SizeMask);
778 *BlockFooter(memory,SizeOfBlock(memory))=SizeOfBlock(memory);
779 *BlockHeader(NextBlock(memory))&=(~PreviousBlockBit);
780 InsertFreeBlock(memory,AllocationPolicy(SizeOfBlock(memory)));
781 UnlockSemaphoreInfo(memory_semaphore);
783 return((void *) NULL);
787 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
791 % R e s e t M a g i c k M e m o r y %
795 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
797 % ResetMagickMemory() fills the first size bytes of the memory area pointed to
798 % by memory with the constant byte c.
800 % The format of the ResetMagickMemory method is:
802 % void *ResetMagickMemory(void *memory,int byte,const size_t size)
804 % A description of each parameter follows:
806 % o memory: A pointer to a memory allocation.
808 % o byte: Set the memory to this value.
810 % o size: Size of the memory to reset.
813 MagickExport void *ResetMagickMemory(void *memory,int byte,const size_t size)
815 assert(memory != (void *) NULL);
816 return(memset(memory,byte,size));
820 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
824 % R e s i z e M a g i c k M e m o r y %
828 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
830 % ResizeMagickMemory() changes the size of the memory and returns a pointer to
831 % the (possibly moved) block. The contents will be unchanged up to the
832 % lesser of the new and old sizes.
834 % The format of the ResizeMagickMemory method is:
836 % void *ResizeMagickMemory(void *memory,const size_t size)
838 % A description of each parameter follows:
840 % o memory: A pointer to a memory allocation.
842 % o size: the new size of the allocated memory.
846 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
847 static inline void *ResizeBlock(void *block,size_t size)
852 if (block == (void *) NULL)
853 return(AcquireBlock(size));
854 memory=AcquireBlock(size);
855 if (memory == (void *) NULL)
856 return((void *) NULL);
857 if (size <= (SizeOfBlock(block)-sizeof(size_t)))
858 (void) memcpy(memory,block,size);
860 (void) memcpy(memory,block,SizeOfBlock(block)-sizeof(size_t));
861 memory_info.allocation+=size;
866 MagickExport void *ResizeMagickMemory(void *memory,const size_t size)
871 if (memory == (void *) NULL)
872 return(AcquireMagickMemory(size));
873 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
874 block=memory_methods.resize_memory_handler(memory,size == 0 ? 1UL : size);
875 if (block == (void *) NULL)
876 memory=RelinquishMagickMemory(memory);
878 LockSemaphoreInfo(memory_semaphore);
879 block=ResizeBlock(memory,size == 0 ? 1UL : size);
880 if (block == (void *) NULL)
882 if (ExpandHeap(size == 0 ? 1UL : size) == MagickFalse)
884 UnlockSemaphoreInfo(memory_semaphore);
885 memory=RelinquishMagickMemory(memory);
886 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
888 block=ResizeBlock(memory,size == 0 ? 1UL : size);
889 assert(block != (void *) NULL);
891 UnlockSemaphoreInfo(memory_semaphore);
892 memory=RelinquishMagickMemory(memory);
898 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
902 % R e s i z e Q u a n t u m M e m o r y %
906 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
908 % ResizeQuantumMemory() changes the size of the memory and returns a pointer
909 % to the (possibly moved) block. The contents will be unchanged up to the
910 % lesser of the new and old sizes.
912 % The format of the ResizeQuantumMemory method is:
914 % void *ResizeQuantumMemory(void *memory,const size_t count,
915 % const size_t quantum)
917 % A description of each parameter follows:
919 % o memory: A pointer to a memory allocation.
921 % o count: the number of quantum elements to allocate.
923 % o quantum: the number of bytes in each quantum.
926 MagickExport void *ResizeQuantumMemory(void *memory,const size_t count,
927 const size_t quantum)
933 if ((count == 0) || (quantum != (size/count)))
935 memory=RelinquishMagickMemory(memory);
937 return((void *) NULL);
939 return(ResizeMagickMemory(memory,size));
943 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
947 % S e t M a g i c k M e m o r y M e t h o d s %
951 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
953 % SetMagickMemoryMethods() sets the methods to acquire, resize, and destroy
956 % The format of the SetMagickMemoryMethods() method is:
958 % SetMagickMemoryMethods(AcquireMemoryHandler acquire_memory_handler,
959 % ResizeMemoryHandler resize_memory_handler,
960 % DestroyMemoryHandler destroy_memory_handler)
962 % A description of each parameter follows:
964 % o acquire_memory_handler: method to acquire memory (e.g. malloc).
966 % o resize_memory_handler: method to resize memory (e.g. realloc).
968 % o destroy_memory_handler: method to destroy memory (e.g. free).
971 MagickExport void SetMagickMemoryMethods(
972 AcquireMemoryHandler acquire_memory_handler,
973 ResizeMemoryHandler resize_memory_handler,
974 DestroyMemoryHandler destroy_memory_handler)
979 if (acquire_memory_handler != (AcquireMemoryHandler) NULL)
980 memory_methods.acquire_memory_handler=acquire_memory_handler;
981 if (resize_memory_handler != (ResizeMemoryHandler) NULL)
982 memory_methods.resize_memory_handler=resize_memory_handler;
983 if (destroy_memory_handler != (DestroyMemoryHandler) NULL)
984 memory_methods.destroy_memory_handler=destroy_memory_handler;