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-2016 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[MagickPathExtent];
147 typedef struct _MemoryPool
153 *blocks[MaxBlocks+1];
159 *segments[MaxSegments],
160 segment_pool[MaxSegments];
167 static void* MSCMalloc(size_t size)
171 static void* MSCRealloc(void* ptr, size_t size)
173 return realloc(ptr, size);
175 static void MSCFree(void* ptr)
181 static MagickMemoryMethods
185 (AcquireMemoryHandler) MSCMalloc,
186 (ResizeMemoryHandler) MSCRealloc,
187 (DestroyMemoryHandler) MSCFree
189 (AcquireMemoryHandler) malloc,
190 (ResizeMemoryHandler) realloc,
191 (DestroyMemoryHandler) free
194 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
199 *memory_semaphore = (SemaphoreInfo *) NULL;
201 static volatile DataSegmentInfo
202 *free_segments = (DataSegmentInfo *) NULL;
205 Forward declarations.
207 static MagickBooleanType
212 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
216 % A c q u i r e A l i g n e d M e m o r y %
220 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
222 % AcquireAlignedMemory() returns a pointer to a block of memory at least size
223 % bytes whose address is a multiple of 16*sizeof(void *).
225 % The format of the AcquireAlignedMemory method is:
227 % void *AcquireAlignedMemory(const size_t count,const size_t quantum)
229 % A description of each parameter follows:
231 % o count: the number of quantum elements to allocate.
233 % o quantum: the number of bytes in each quantum.
236 static MagickBooleanType CheckMemoryOverflow(const size_t count,
237 const size_t quantum)
243 if ((count == 0) || (quantum != (size/count)))
251 MagickExport void *AcquireAlignedMemory(const size_t count,const size_t quantum)
253 #define AlignedExtent(size,alignment) \
254 (((size)+((alignment)-1)) & ~((alignment)-1))
264 if (CheckMemoryOverflow(count,quantum) != MagickFalse)
265 return((void *) NULL);
267 alignment=CACHE_LINE_SIZE;
269 extent=AlignedExtent(size,alignment);
270 if ((size == 0) || (alignment < sizeof(void *)) || (extent < size))
271 return((void *) NULL);
272 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
273 if (posix_memalign(&memory,alignment,extent) != 0)
275 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
276 memory=_aligned_malloc(extent,alignment);
282 extent=(size+alignment-1)+sizeof(void *);
288 memory=(void *) AlignedExtent((size_t) p+sizeof(void *),alignment);
289 *((void **) memory-1)=p;
297 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
299 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
303 + A c q u i r e B l o c k %
307 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
309 % AcquireBlock() returns a pointer to a block of memory at least size bytes
310 % suitably aligned for any use.
312 % The format of the AcquireBlock method is:
314 % void *AcquireBlock(const size_t size)
316 % A description of each parameter follows:
318 % o size: the size of the memory in bytes to allocate.
322 static inline size_t AllocationPolicy(size_t size)
328 The linear distribution.
331 assert(size % (4*sizeof(size_t)) == 0);
332 if (size <= BlockThreshold)
333 return(size/(4*sizeof(size_t)));
335 Check for the largest block size.
337 if (size > (size_t) (BlockThreshold*(1L << (MaxBlockExponent-1L))))
338 return(MaxBlocks-1L);
340 Otherwise use a power of two distribution.
342 blocksize=BlockThreshold/(4*sizeof(size_t));
343 for ( ; size > BlockThreshold; size/=2)
345 assert(blocksize > (BlockThreshold/(4*sizeof(size_t))));
346 assert(blocksize < (MaxBlocks-1L));
350 static inline void InsertFreeBlock(void *block,const size_t i)
359 size=SizeOfBlock(block);
360 previous=(void *) NULL;
361 next=memory_pool.blocks[i];
362 while ((next != (void *) NULL) && (SizeOfBlock(next) < size))
365 next=NextBlockInList(next);
367 PreviousBlockInList(block)=previous;
368 NextBlockInList(block)=next;
369 if (previous != (void *) NULL)
370 NextBlockInList(previous)=block;
372 memory_pool.blocks[i]=block;
373 if (next != (void *) NULL)
374 PreviousBlockInList(next)=block;
377 static inline void RemoveFreeBlock(void *block,const size_t i)
383 next=NextBlockInList(block);
384 previous=PreviousBlockInList(block);
385 if (previous == (void *) NULL)
386 memory_pool.blocks[i]=next;
388 NextBlockInList(previous)=next;
389 if (next != (void *) NULL)
390 PreviousBlockInList(next)=previous;
393 static void *AcquireBlock(size_t size)
404 size=(size_t) (size+sizeof(size_t)+6*sizeof(size_t)-1) & -(4U*sizeof(size_t));
405 i=AllocationPolicy(size);
406 block=memory_pool.blocks[i];
407 while ((block != (void *) NULL) && (SizeOfBlock(block) < size))
408 block=NextBlockInList(block);
409 if (block == (void *) NULL)
412 while (memory_pool.blocks[i] == (void *) NULL)
414 block=memory_pool.blocks[i];
416 return((void *) NULL);
418 assert((*BlockHeader(NextBlock(block)) & PreviousBlockBit) == 0);
419 assert(SizeOfBlock(block) >= size);
420 RemoveFreeBlock(block,AllocationPolicy(SizeOfBlock(block)));
421 if (SizeOfBlock(block) > size)
432 next=(char *) block+size;
433 blocksize=SizeOfBlock(block)-size;
434 *BlockHeader(next)=blocksize;
435 *BlockFooter(next,blocksize)=blocksize;
436 InsertFreeBlock(next,AllocationPolicy(blocksize));
437 *BlockHeader(block)=size | (*BlockHeader(block) & ~SizeMask);
439 assert(size == SizeOfBlock(block));
440 *BlockHeader(NextBlock(block))|=PreviousBlockBit;
441 memory_pool.allocation+=size;
447 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
451 % A c q u i r e M a g i c k M e m o r y %
455 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
457 % AcquireMagickMemory() returns a pointer to a block of memory at least size
458 % bytes suitably aligned for any use.
460 % The format of the AcquireMagickMemory method is:
462 % void *AcquireMagickMemory(const size_t size)
464 % A description of each parameter follows:
466 % o size: the size of the memory in bytes to allocate.
469 MagickExport void *AcquireMagickMemory(const size_t size)
474 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
475 memory=memory_methods.acquire_memory_handler(size == 0 ? 1UL : size);
477 if (memory_semaphore == (SemaphoreInfo *) NULL)
478 ActivateSemaphoreInfo(&memory_semaphore);
479 if (free_segments == (DataSegmentInfo *) NULL)
481 LockSemaphoreInfo(memory_semaphore);
482 if (free_segments == (DataSegmentInfo *) NULL)
487 assert(2*sizeof(size_t) > (size_t) (~SizeMask));
488 (void) ResetMagickMemory(&memory_pool,0,sizeof(memory_pool));
489 memory_pool.allocation=SegmentSize;
490 memory_pool.blocks[MaxBlocks]=(void *) (-1);
491 for (i=0; i < MaxSegments; i++)
494 memory_pool.segment_pool[i].previous=
495 (&memory_pool.segment_pool[i-1]);
496 if (i != (MaxSegments-1))
497 memory_pool.segment_pool[i].next=(&memory_pool.segment_pool[i+1]);
499 free_segments=(&memory_pool.segment_pool[0]);
501 UnlockSemaphoreInfo(memory_semaphore);
503 LockSemaphoreInfo(memory_semaphore);
504 memory=AcquireBlock(size == 0 ? 1UL : size);
505 if (memory == (void *) NULL)
507 if (ExpandHeap(size == 0 ? 1UL : size) != MagickFalse)
508 memory=AcquireBlock(size == 0 ? 1UL : size);
510 UnlockSemaphoreInfo(memory_semaphore);
516 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
520 % A c q u i r e Q u a n t u m M e m o r y %
524 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
526 % AcquireQuantumMemory() returns a pointer to a block of memory at least
527 % count * quantum bytes suitably aligned for any use.
529 % The format of the AcquireQuantumMemory method is:
531 % void *AcquireQuantumMemory(const size_t count,const size_t quantum)
533 % A description of each parameter follows:
535 % o count: the number of quantum elements to allocate.
537 % o quantum: the number of bytes in each quantum.
540 MagickExport void *AcquireQuantumMemory(const size_t count,const size_t quantum)
545 if (CheckMemoryOverflow(count,quantum) != MagickFalse)
546 return((void *) NULL);
547 extent=count*quantum;
548 return(AcquireMagickMemory(extent));
552 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
556 % A c q u i r e V i r t u a l M e m o r y %
560 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
562 % AcquireVirtualMemory() allocates a pointer to a block of memory at least size
563 % bytes suitably aligned for any use.
565 % The format of the AcquireVirtualMemory method is:
567 % MemoryInfo *AcquireVirtualMemory(const size_t count,const size_t quantum)
569 % A description of each parameter follows:
571 % o count: the number of quantum elements to allocate.
573 % o quantum: the number of bytes in each quantum.
576 MagickExport MemoryInfo *AcquireVirtualMemory(const size_t count,
577 const size_t quantum)
585 if (CheckMemoryOverflow(count,quantum) != MagickFalse)
586 return((MemoryInfo *) NULL);
587 memory_info=(MemoryInfo *) MagickAssumeAligned(AcquireAlignedMemory(1,
588 sizeof(*memory_info)));
589 if (memory_info == (MemoryInfo *) NULL)
590 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
591 (void) ResetMagickMemory(memory_info,0,sizeof(*memory_info));
592 extent=count*quantum;
593 memory_info->length=extent;
594 memory_info->signature=MagickCoreSignature;
595 if (AcquireMagickResource(MemoryResource,extent) != MagickFalse)
597 memory_info->blob=AcquireAlignedMemory(1,extent);
598 if (memory_info->blob != NULL)
600 memory_info->type=AlignedVirtualMemory;
604 RelinquishMagickResource(MemoryResource,extent);
605 if (AcquireMagickResource(MapResource,extent) != MagickFalse)
608 Heap memory failed, try anonymous memory mapping.
610 memory_info->blob=MapBlob(-1,IOMode,0,extent);
611 if (memory_info->blob != NULL)
613 memory_info->type=MapVirtualMemory;
616 if (AcquireMagickResource(DiskResource,extent) != MagickFalse)
622 Anonymous memory mapping failed, try file-backed memory mapping.
623 If the MapResource request failed, there is no point in trying
624 file-backed memory mapping.
626 file=AcquireUniqueFileResource(memory_info->filename);
629 if ((lseek(file,extent-1,SEEK_SET) == (extent-1)) &&
630 (write(file,"",1) == 1))
632 memory_info->blob=MapBlob(file,IOMode,0,extent);
633 if (memory_info->blob != NULL)
636 memory_info->type=MapVirtualMemory;
641 File-backed memory mapping failed, delete the temporary file.
644 (void) RelinquishUniqueFileResource(memory_info->filename);
645 *memory_info->filename = '\0';
648 RelinquishMagickResource(DiskResource,extent);
650 RelinquishMagickResource(MapResource,extent);
651 if (memory_info->blob == NULL)
653 memory_info->blob=AcquireMagickMemory(extent);
654 if (memory_info->blob != NULL)
655 memory_info->type=UnalignedVirtualMemory;
657 if (memory_info->blob == NULL)
658 memory_info=RelinquishVirtualMemory(memory_info);
663 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
667 % C o p y M a g i c k M e m o r y %
671 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
673 % CopyMagickMemory() copies size bytes from memory area source to the
674 % destination. Copying between objects that overlap will take place
675 % correctly. It returns destination.
677 % The format of the CopyMagickMemory method is:
679 % void *CopyMagickMemory(void *destination,const void *source,
682 % A description of each parameter follows:
684 % o destination: the destination.
686 % o source: the source.
688 % o size: the size of the memory in bytes to allocate.
691 MagickExport void *CopyMagickMemory(void *destination,const void *source,
694 register const unsigned char
697 register unsigned char
700 assert(destination != (void *) NULL);
701 assert(source != (const void *) NULL);
702 p=(const unsigned char *) source;
703 q=(unsigned char *) destination;
704 if (((q+size) < p) || (q > (p+size)))
707 default: return(memcpy(destination,source,size));
716 case 0: return(destination);
718 return(memmove(destination,source,size));
722 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
726 + D e s t r o y M a g i c k M e m o r y %
730 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
732 % DestroyMagickMemory() deallocates memory associated with the memory manager.
734 % The format of the DestroyMagickMemory method is:
736 % DestroyMagickMemory(void)
739 MagickExport void DestroyMagickMemory(void)
741 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
745 if (memory_semaphore == (SemaphoreInfo *) NULL)
746 ActivateSemaphoreInfo(&memory_semaphore);
747 LockSemaphoreInfo(memory_semaphore);
748 for (i=0; i < (ssize_t) memory_pool.number_segments; i++)
749 if (memory_pool.segments[i]->mapped == MagickFalse)
750 memory_methods.destroy_memory_handler(
751 memory_pool.segments[i]->allocation);
753 (void) UnmapBlob(memory_pool.segments[i]->allocation,
754 memory_pool.segments[i]->length);
755 free_segments=(DataSegmentInfo *) NULL;
756 (void) ResetMagickMemory(&memory_pool,0,sizeof(memory_pool));
757 UnlockSemaphoreInfo(memory_semaphore);
758 RelinquishSemaphoreInfo(&memory_semaphore);
762 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
764 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
768 + E x p a n d H e a p %
772 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
774 % ExpandHeap() get more memory from the system. It returns MagickTrue on
775 % success otherwise MagickFalse.
777 % The format of the ExpandHeap method is:
779 % MagickBooleanType ExpandHeap(size_t size)
781 % A description of each parameter follows:
783 % o size: the size of the memory in bytes we require.
786 static MagickBooleanType ExpandHeap(size_t size)
806 blocksize=((size+12*sizeof(size_t))+SegmentSize-1) & -SegmentSize;
807 assert(memory_pool.number_segments < MaxSegments);
808 segment=MapBlob(-1,IOMode,0,blocksize);
809 mapped=segment != (void *) NULL ? MagickTrue : MagickFalse;
810 if (segment == (void *) NULL)
811 segment=(void *) memory_methods.acquire_memory_handler(blocksize);
812 if (segment == (void *) NULL)
814 segment_info=(DataSegmentInfo *) free_segments;
815 free_segments=segment_info->next;
816 segment_info->mapped=mapped;
817 segment_info->length=blocksize;
818 segment_info->allocation=segment;
819 segment_info->bound=(char *) segment+blocksize;
820 i=(ssize_t) memory_pool.number_segments-1;
821 for ( ; (i >= 0) && (memory_pool.segments[i]->allocation > segment); i--)
822 memory_pool.segments[i+1]=memory_pool.segments[i];
823 memory_pool.segments[i+1]=segment_info;
824 memory_pool.number_segments++;
825 size=blocksize-12*sizeof(size_t);
826 block=(char *) segment_info->allocation+4*sizeof(size_t);
827 *BlockHeader(block)=size | PreviousBlockBit;
828 *BlockFooter(block,size)=size;
829 InsertFreeBlock(block,AllocationPolicy(size));
830 block=NextBlock(block);
831 assert(block < segment_info->bound);
832 *BlockHeader(block)=2*sizeof(size_t);
833 *BlockHeader(NextBlock(block))=PreviousBlockBit;
839 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
843 % G e t M a g i c k M e m o r y M e t h o d s %
847 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
849 % GetMagickMemoryMethods() gets the methods to acquire, resize, and destroy
852 % The format of the GetMagickMemoryMethods() method is:
854 % void GetMagickMemoryMethods(AcquireMemoryHandler *acquire_memory_handler,
855 % ResizeMemoryHandler *resize_memory_handler,
856 % DestroyMemoryHandler *destroy_memory_handler)
858 % A description of each parameter follows:
860 % o acquire_memory_handler: method to acquire memory (e.g. malloc).
862 % o resize_memory_handler: method to resize memory (e.g. realloc).
864 % o destroy_memory_handler: method to destroy memory (e.g. free).
867 MagickExport void GetMagickMemoryMethods(
868 AcquireMemoryHandler *acquire_memory_handler,
869 ResizeMemoryHandler *resize_memory_handler,
870 DestroyMemoryHandler *destroy_memory_handler)
872 assert(acquire_memory_handler != (AcquireMemoryHandler *) NULL);
873 assert(resize_memory_handler != (ResizeMemoryHandler *) NULL);
874 assert(destroy_memory_handler != (DestroyMemoryHandler *) NULL);
875 *acquire_memory_handler=memory_methods.acquire_memory_handler;
876 *resize_memory_handler=memory_methods.resize_memory_handler;
877 *destroy_memory_handler=memory_methods.destroy_memory_handler;
881 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
885 % G e t V i r t u a l M e m o r y B l o b %
889 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
891 % GetVirtualMemoryBlob() returns the virtual memory blob associated with the
892 % specified MemoryInfo structure.
894 % The format of the GetVirtualMemoryBlob method is:
896 % void *GetVirtualMemoryBlob(const MemoryInfo *memory_info)
898 % A description of each parameter follows:
900 % o memory_info: The MemoryInfo structure.
902 MagickExport void *GetVirtualMemoryBlob(const MemoryInfo *memory_info)
904 assert(memory_info != (const MemoryInfo *) NULL);
905 assert(memory_info->signature == MagickCoreSignature);
906 return(memory_info->blob);
910 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
914 % R e l i n q u i s h A l i g n e d M e m o r y %
918 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
920 % RelinquishAlignedMemory() frees memory acquired with AcquireAlignedMemory()
923 % The format of the RelinquishAlignedMemory method is:
925 % void *RelinquishAlignedMemory(void *memory)
927 % A description of each parameter follows:
929 % o memory: A pointer to a block of memory to free for reuse.
932 MagickExport void *RelinquishAlignedMemory(void *memory)
934 if (memory == (void *) NULL)
935 return((void *) NULL);
936 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
938 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
939 _aligned_free(memory);
941 free(*((void **) memory-1));
947 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
951 % R e l i n q u i s h M a g i c k M e m o r y %
955 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
957 % RelinquishMagickMemory() frees memory acquired with AcquireMagickMemory()
958 % or AcquireQuantumMemory() for reuse.
960 % The format of the RelinquishMagickMemory method is:
962 % void *RelinquishMagickMemory(void *memory)
964 % A description of each parameter follows:
966 % o memory: A pointer to a block of memory to free for reuse.
969 MagickExport void *RelinquishMagickMemory(void *memory)
971 if (memory == (void *) NULL)
972 return((void *) NULL);
973 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
974 memory_methods.destroy_memory_handler(memory);
976 LockSemaphoreInfo(memory_semaphore);
977 assert((SizeOfBlock(memory) % (4*sizeof(size_t))) == 0);
978 assert((*BlockHeader(NextBlock(memory)) & PreviousBlockBit) != 0);
979 if ((*BlockHeader(memory) & PreviousBlockBit) == 0)
985 Coalesce with previous adjacent block.
987 previous=PreviousBlock(memory);
988 RemoveFreeBlock(previous,AllocationPolicy(SizeOfBlock(previous)));
989 *BlockHeader(previous)=(SizeOfBlock(previous)+SizeOfBlock(memory)) |
990 (*BlockHeader(previous) & ~SizeMask);
993 if ((*BlockHeader(NextBlock(NextBlock(memory))) & PreviousBlockBit) == 0)
999 Coalesce with next adjacent block.
1001 next=NextBlock(memory);
1002 RemoveFreeBlock(next,AllocationPolicy(SizeOfBlock(next)));
1003 *BlockHeader(memory)=(SizeOfBlock(memory)+SizeOfBlock(next)) |
1004 (*BlockHeader(memory) & ~SizeMask);
1006 *BlockFooter(memory,SizeOfBlock(memory))=SizeOfBlock(memory);
1007 *BlockHeader(NextBlock(memory))&=(~PreviousBlockBit);
1008 InsertFreeBlock(memory,AllocationPolicy(SizeOfBlock(memory)));
1009 UnlockSemaphoreInfo(memory_semaphore);
1011 return((void *) NULL);
1015 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1019 % R e l i n q u i s h V i r t u a l M e m o r y %
1023 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1025 % RelinquishVirtualMemory() frees memory acquired with AcquireVirtualMemory().
1027 % The format of the RelinquishVirtualMemory method is:
1029 % MemoryInfo *RelinquishVirtualMemory(MemoryInfo *memory_info)
1031 % A description of each parameter follows:
1033 % o memory_info: A pointer to a block of memory to free for reuse.
1036 MagickExport MemoryInfo *RelinquishVirtualMemory(MemoryInfo *memory_info)
1038 assert(memory_info != (MemoryInfo *) NULL);
1039 assert(memory_info->signature == MagickCoreSignature);
1040 if (memory_info->blob != (void *) NULL)
1041 switch (memory_info->type)
1043 case AlignedVirtualMemory:
1045 memory_info->blob=RelinquishAlignedMemory(memory_info->blob);
1046 RelinquishMagickResource(MemoryResource,memory_info->length);
1049 case MapVirtualMemory:
1051 (void) UnmapBlob(memory_info->blob,memory_info->length);
1052 memory_info->blob=NULL;
1053 RelinquishMagickResource(MapResource,memory_info->length);
1054 if (*memory_info->filename != '\0')
1056 (void) RelinquishUniqueFileResource(memory_info->filename);
1057 RelinquishMagickResource(DiskResource,memory_info->length);
1061 case UnalignedVirtualMemory:
1064 memory_info->blob=RelinquishMagickMemory(memory_info->blob);
1068 memory_info->signature=(~MagickCoreSignature);
1069 memory_info=(MemoryInfo *) RelinquishAlignedMemory(memory_info);
1070 return(memory_info);
1074 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1078 % R e s e t M a g i c k M e m o r y %
1082 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1084 % ResetMagickMemory() fills the first size bytes of the memory area pointed to
1085 % by memory with the constant byte c.
1087 % The format of the ResetMagickMemory method is:
1089 % void *ResetMagickMemory(void *memory,int byte,const size_t size)
1091 % A description of each parameter follows:
1093 % o memory: a pointer to a memory allocation.
1095 % o byte: set the memory to this value.
1097 % o size: size of the memory to reset.
1100 MagickExport void *ResetMagickMemory(void *memory,int byte,const size_t size)
1102 assert(memory != (void *) NULL);
1103 return(memset(memory,byte,size));
1107 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1111 % R e s i z e M a g i c k M e m o r y %
1115 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1117 % ResizeMagickMemory() changes the size of the memory and returns a pointer to
1118 % the (possibly moved) block. The contents will be unchanged up to the
1119 % lesser of the new and old sizes.
1121 % The format of the ResizeMagickMemory method is:
1123 % void *ResizeMagickMemory(void *memory,const size_t size)
1125 % A description of each parameter follows:
1127 % o memory: A pointer to a memory allocation.
1129 % o size: the new size of the allocated memory.
1133 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
1134 static inline void *ResizeBlock(void *block,size_t size)
1139 if (block == (void *) NULL)
1140 return(AcquireBlock(size));
1141 memory=AcquireBlock(size);
1142 if (memory == (void *) NULL)
1143 return((void *) NULL);
1144 if (size <= (SizeOfBlock(block)-sizeof(size_t)))
1145 (void) memcpy(memory,block,size);
1147 (void) memcpy(memory,block,SizeOfBlock(block)-sizeof(size_t));
1148 memory_pool.allocation+=size;
1153 MagickExport void *ResizeMagickMemory(void *memory,const size_t size)
1158 if (memory == (void *) NULL)
1159 return(AcquireMagickMemory(size));
1160 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
1161 block=memory_methods.resize_memory_handler(memory,size == 0 ? 1UL : size);
1162 if (block == (void *) NULL)
1163 memory=RelinquishMagickMemory(memory);
1165 LockSemaphoreInfo(memory_semaphore);
1166 block=ResizeBlock(memory,size == 0 ? 1UL : size);
1167 if (block == (void *) NULL)
1169 if (ExpandHeap(size == 0 ? 1UL : size) == MagickFalse)
1171 UnlockSemaphoreInfo(memory_semaphore);
1172 memory=RelinquishMagickMemory(memory);
1173 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1175 block=ResizeBlock(memory,size == 0 ? 1UL : size);
1176 assert(block != (void *) NULL);
1178 UnlockSemaphoreInfo(memory_semaphore);
1179 memory=RelinquishMagickMemory(memory);
1185 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1189 % R e s i z e Q u a n t u m M e m o r y %
1193 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1195 % ResizeQuantumMemory() changes the size of the memory and returns a pointer
1196 % to the (possibly moved) block. The contents will be unchanged up to the
1197 % lesser of the new and old sizes.
1199 % The format of the ResizeQuantumMemory method is:
1201 % void *ResizeQuantumMemory(void *memory,const size_t count,
1202 % const size_t quantum)
1204 % A description of each parameter follows:
1206 % o memory: A pointer to a memory allocation.
1208 % o count: the number of quantum elements to allocate.
1210 % o quantum: the number of bytes in each quantum.
1213 MagickExport void *ResizeQuantumMemory(void *memory,const size_t count,
1214 const size_t quantum)
1219 if (CheckMemoryOverflow(count,quantum) != MagickFalse)
1221 memory=RelinquishMagickMemory(memory);
1222 return((void *) NULL);
1224 extent=count*quantum;
1225 return(ResizeMagickMemory(memory,extent));
1229 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1233 % S e t M a g i c k M e m o r y M e t h o d s %
1237 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1239 % SetMagickMemoryMethods() sets the methods to acquire, resize, and destroy
1240 % memory. Your custom memory methods must be set prior to the
1241 % MagickCoreGenesis() method.
1243 % The format of the SetMagickMemoryMethods() method is:
1245 % SetMagickMemoryMethods(AcquireMemoryHandler acquire_memory_handler,
1246 % ResizeMemoryHandler resize_memory_handler,
1247 % DestroyMemoryHandler destroy_memory_handler)
1249 % A description of each parameter follows:
1251 % o acquire_memory_handler: method to acquire memory (e.g. malloc).
1253 % o resize_memory_handler: method to resize memory (e.g. realloc).
1255 % o destroy_memory_handler: method to destroy memory (e.g. free).
1258 MagickExport void SetMagickMemoryMethods(
1259 AcquireMemoryHandler acquire_memory_handler,
1260 ResizeMemoryHandler resize_memory_handler,
1261 DestroyMemoryHandler destroy_memory_handler)
1266 if (acquire_memory_handler != (AcquireMemoryHandler) NULL)
1267 memory_methods.acquire_memory_handler=acquire_memory_handler;
1268 if (resize_memory_handler != (ResizeMemoryHandler) NULL)
1269 memory_methods.resize_memory_handler=resize_memory_handler;
1270 if (destroy_memory_handler != (DestroyMemoryHandler) NULL)
1271 memory_methods.destroy_memory_handler=destroy_memory_handler;