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-2014 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36 % Segregate our memory requirements from any program that calls our API. This
37 % should help reduce the risk of others changing our program state or causing
40 % Our custom memory allocation manager implements a best-fit allocation policy
41 % using segregated free lists. It uses a linear distribution of size classes
42 % for lower sizes and a power of two distribution of size classes at higher
43 % sizes. It is based on the paper, "Fast Memory Allocation using Lazy Fits."
44 % written by Yoo C. Chung.
46 % By default, ANSI memory methods are called (e.g. malloc). Use the
47 % custom memory allocator by defining MAGICKCORE_ZERO_CONFIGURATION_SUPPORT
48 % to allocate memory with private anonymous mapping rather than from the
56 #include "MagickCore/studio.h"
57 #include "MagickCore/blob.h"
58 #include "MagickCore/blob-private.h"
59 #include "MagickCore/exception.h"
60 #include "MagickCore/exception-private.h"
61 #include "MagickCore/memory_.h"
62 #include "MagickCore/memory-private.h"
63 #include "MagickCore/resource_.h"
64 #include "MagickCore/semaphore.h"
65 #include "MagickCore/string_.h"
66 #include "MagickCore/utility-private.h"
71 #define BlockFooter(block,size) \
72 ((size_t *) ((char *) (block)+(size)-2*sizeof(size_t)))
73 #define BlockHeader(block) ((size_t *) (block)-1)
74 #define BlockSize 4096
75 #define BlockThreshold 1024
76 #define MaxBlockExponent 16
77 #define MaxBlocks ((BlockThreshold/(4*sizeof(size_t)))+MaxBlockExponent+1)
78 #define MaxSegments 1024
79 #define MemoryGuard ((0xdeadbeef << 31)+0xdeafdeed)
80 #define NextBlock(block) ((char *) (block)+SizeOfBlock(block))
81 #define NextBlockInList(block) (*(void **) (block))
82 #define PreviousBlock(block) ((char *) (block)-(*((size_t *) (block)-2)))
83 #define PreviousBlockBit 0x01
84 #define PreviousBlockInList(block) (*((void **) (block)+1))
85 #define SegmentSize (2*1024*1024)
86 #define SizeMask (~0x01)
87 #define SizeOfBlock(block) (*BlockHeader(block) & SizeMask)
94 UndefinedVirtualMemory,
97 UnalignedVirtualMemory
100 typedef struct _DataSegmentInfo
112 struct _DataSegmentInfo
117 typedef struct _MagickMemoryMethods
120 acquire_memory_handler;
123 resize_memory_handler;
126 destroy_memory_handler;
127 } MagickMemoryMethods;
132 filename[MaxTextExtent];
147 typedef struct _MemoryPool
153 *blocks[MaxBlocks+1];
159 *segments[MaxSegments],
160 segment_pool[MaxSegments];
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 MagickExport void *AcquireAlignedMemory(const size_t count,const size_t quantum)
238 #define AlignedExtent(size,alignment) \
239 (((size)+((alignment)-1)) & ~((alignment)-1))
250 if ((count == 0) || (quantum != (size/count)))
253 return((void *) NULL);
256 alignment=CACHE_LINE_SIZE;
257 extent=AlignedExtent(size,alignment);
258 if ((size == 0) || (alignment < sizeof(void *)) || (extent < size))
259 return((void *) NULL);
260 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
261 if (posix_memalign(&memory,alignment,extent) != 0)
263 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
264 memory=_aligned_malloc(extent,alignment);
270 extent=(size+alignment-1)+sizeof(void *);
276 memory=(void *) AlignedExtent((size_t) p+sizeof(void *),alignment);
277 *((void **) memory-1)=p;
285 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
287 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
291 + A c q u i r e B l o c k %
295 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
297 % AcquireBlock() returns a pointer to a block of memory at least size bytes
298 % suitably aligned for any use.
300 % The format of the AcquireBlock method is:
302 % void *AcquireBlock(const size_t size)
304 % A description of each parameter follows:
306 % o size: the size of the memory in bytes to allocate.
310 static inline size_t AllocationPolicy(size_t size)
316 The linear distribution.
319 assert(size % (4*sizeof(size_t)) == 0);
320 if (size <= BlockThreshold)
321 return(size/(4*sizeof(size_t)));
323 Check for the largest block size.
325 if (size > (size_t) (BlockThreshold*(1L << (MaxBlockExponent-1L))))
326 return(MaxBlocks-1L);
328 Otherwise use a power of two distribution.
330 blocksize=BlockThreshold/(4*sizeof(size_t));
331 for ( ; size > BlockThreshold; size/=2)
333 assert(blocksize > (BlockThreshold/(4*sizeof(size_t))));
334 assert(blocksize < (MaxBlocks-1L));
338 static inline void InsertFreeBlock(void *block,const size_t i)
347 size=SizeOfBlock(block);
348 previous=(void *) NULL;
349 next=memory_pool.blocks[i];
350 while ((next != (void *) NULL) && (SizeOfBlock(next) < size))
353 next=NextBlockInList(next);
355 PreviousBlockInList(block)=previous;
356 NextBlockInList(block)=next;
357 if (previous != (void *) NULL)
358 NextBlockInList(previous)=block;
360 memory_pool.blocks[i]=block;
361 if (next != (void *) NULL)
362 PreviousBlockInList(next)=block;
365 static inline void RemoveFreeBlock(void *block,const size_t i)
371 next=NextBlockInList(block);
372 previous=PreviousBlockInList(block);
373 if (previous == (void *) NULL)
374 memory_pool.blocks[i]=next;
376 NextBlockInList(previous)=next;
377 if (next != (void *) NULL)
378 PreviousBlockInList(next)=previous;
381 static void *AcquireBlock(size_t size)
392 size=(size_t) (size+sizeof(size_t)+6*sizeof(size_t)-1) & -(4U*sizeof(size_t));
393 i=AllocationPolicy(size);
394 block=memory_pool.blocks[i];
395 while ((block != (void *) NULL) && (SizeOfBlock(block) < size))
396 block=NextBlockInList(block);
397 if (block == (void *) NULL)
400 while (memory_pool.blocks[i] == (void *) NULL)
402 block=memory_pool.blocks[i];
404 return((void *) NULL);
406 assert((*BlockHeader(NextBlock(block)) & PreviousBlockBit) == 0);
407 assert(SizeOfBlock(block) >= size);
408 RemoveFreeBlock(block,AllocationPolicy(SizeOfBlock(block)));
409 if (SizeOfBlock(block) > size)
420 next=(char *) block+size;
421 blocksize=SizeOfBlock(block)-size;
422 *BlockHeader(next)=blocksize;
423 *BlockFooter(next,blocksize)=blocksize;
424 InsertFreeBlock(next,AllocationPolicy(blocksize));
425 *BlockHeader(block)=size | (*BlockHeader(block) & ~SizeMask);
427 assert(size == SizeOfBlock(block));
428 *BlockHeader(NextBlock(block))|=PreviousBlockBit;
429 memory_pool.allocation+=size;
435 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
439 % A c q u i r e M a g i c k M e m o r y %
443 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
445 % AcquireMagickMemory() returns a pointer to a block of memory at least size
446 % bytes suitably aligned for any use.
448 % The format of the AcquireMagickMemory method is:
450 % void *AcquireMagickMemory(const size_t size)
452 % A description of each parameter follows:
454 % o size: the size of the memory in bytes to allocate.
457 MagickExport void *AcquireMagickMemory(const size_t size)
462 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
463 memory=memory_methods.acquire_memory_handler(size == 0 ? 1UL : size);
465 if (memory_semaphore == (SemaphoreInfo *) NULL)
466 memory_semaphore=AcquireSemaphoreInfo();
467 if (free_segments == (DataSegmentInfo *) NULL)
469 LockSemaphoreInfo(memory_semaphore);
470 if (free_segments == (DataSegmentInfo *) NULL)
475 assert(2*sizeof(size_t) > (size_t) (~SizeMask));
476 (void) ResetMagickMemory(&memory_pool,0,sizeof(memory_pool));
477 memory_pool.allocation=SegmentSize;
478 memory_pool.blocks[MaxBlocks]=(void *) (-1);
479 for (i=0; i < MaxSegments; i++)
482 memory_pool.segment_pool[i].previous=
483 (&memory_pool.segment_pool[i-1]);
484 if (i != (MaxSegments-1))
485 memory_pool.segment_pool[i].next=(&memory_pool.segment_pool[i+1]);
487 free_segments=(&memory_pool.segment_pool[0]);
489 UnlockSemaphoreInfo(memory_semaphore);
491 LockSemaphoreInfo(memory_semaphore);
492 memory=AcquireBlock(size == 0 ? 1UL : size);
493 if (memory == (void *) NULL)
495 if (ExpandHeap(size == 0 ? 1UL : size) != MagickFalse)
496 memory=AcquireBlock(size == 0 ? 1UL : size);
498 UnlockSemaphoreInfo(memory_semaphore);
504 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
508 % A c q u i r e Q u a n t u m M e m o r y %
512 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
514 % AcquireQuantumMemory() returns a pointer to a block of memory at least
515 % count * quantum bytes suitably aligned for any use.
517 % The format of the AcquireQuantumMemory method is:
519 % void *AcquireQuantumMemory(const size_t count,const size_t quantum)
521 % A description of each parameter follows:
523 % o count: the number of quantum elements to allocate.
525 % o quantum: the number of bytes in each quantum.
528 MagickExport void *AcquireQuantumMemory(const size_t count,const size_t quantum)
534 if ((count == 0) || (quantum != (size/count)))
537 return((void *) NULL);
539 return(AcquireMagickMemory(size));
543 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
547 % A c q u i r e V i r t u a l M e m o r y %
551 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
553 % AcquireVirtualMemory() allocates a pointer to a block of memory at least size
554 % bytes suitably aligned for any use.
556 % The format of the AcquireVirtualMemory method is:
558 % MemoryInfo *AcquireVirtualMemory(const size_t count,const size_t quantum)
560 % A description of each parameter follows:
562 % o count: the number of quantum elements to allocate.
564 % o quantum: the number of bytes in each quantum.
567 MagickExport MemoryInfo *AcquireVirtualMemory(const size_t count,
568 const size_t quantum)
576 length=count*quantum;
577 if ((count == 0) || (quantum != (length/count)))
580 return((MemoryInfo *) NULL);
582 memory_info=(MemoryInfo *) MagickAssumeAligned(AcquireAlignedMemory(1,
583 sizeof(*memory_info)));
584 if (memory_info == (MemoryInfo *) NULL)
585 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
586 (void) ResetMagickMemory(memory_info,0,sizeof(*memory_info));
587 memory_info->length=length;
588 memory_info->signature=MagickSignature;
589 if (AcquireMagickResource(MemoryResource,length) != MagickFalse)
591 memory_info->blob=AcquireAlignedMemory(1,length);
592 if (memory_info->blob != NULL)
593 memory_info->type=AlignedVirtualMemory;
595 RelinquishMagickResource(MemoryResource,length);
597 if ((memory_info->blob == NULL) &&
598 (AcquireMagickResource(MapResource,length) != MagickFalse))
601 Heap memory failed, try anonymous memory mapping.
603 memory_info->blob=MapBlob(-1,IOMode,0,length);
604 if (memory_info->blob != NULL)
605 memory_info->type=MapVirtualMemory;
607 RelinquishMagickResource(MapResource,length);
609 if (memory_info->blob == NULL)
615 Anonymous memory mapping failed, try file-backed memory mapping.
617 file=AcquireUniqueFileResource(memory_info->filename);
620 if ((lseek(file,length-1,SEEK_SET) >= 0) && (write(file,"",1) == 1))
622 memory_info->blob=MapBlob(file,IOMode,0,length);
623 if (memory_info->blob != NULL)
625 memory_info->type=MapVirtualMemory;
626 (void) AcquireMagickResource(MapResource,length);
632 if (memory_info->blob == NULL)
634 memory_info->blob=AcquireMagickMemory(length);
635 if (memory_info->blob != NULL)
636 memory_info->type=UnalignedVirtualMemory;
638 if (memory_info->blob == NULL)
639 memory_info=RelinquishVirtualMemory(memory_info);
644 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
648 % C o p y M a g i c k M e m o r y %
652 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
654 % CopyMagickMemory() copies size bytes from memory area source to the
655 % destination. Copying between objects that overlap will take place
656 % correctly. It returns destination.
658 % The format of the CopyMagickMemory method is:
660 % void *CopyMagickMemory(void *destination,const void *source,
663 % A description of each parameter follows:
665 % o destination: the destination.
667 % o source: the source.
669 % o size: the size of the memory in bytes to allocate.
672 MagickExport void *CopyMagickMemory(void *destination,const void *source,
675 register const unsigned char
678 register unsigned char
681 assert(destination != (void *) NULL);
682 assert(source != (const void *) NULL);
683 p=(const unsigned char *) source;
684 q=(unsigned char *) destination;
685 if (((q+size) < p) || (q > (p+size)))
688 default: return(memcpy(destination,source,size));
697 case 0: return(destination);
699 return(memmove(destination,source,size));
703 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
707 + D e s t r o y M a g i c k M e m o r y %
711 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
713 % DestroyMagickMemory() deallocates memory associated with the memory manager.
715 % The format of the DestroyMagickMemory method is:
717 % DestroyMagickMemory(void)
720 MagickExport void DestroyMagickMemory(void)
722 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
726 if (memory_semaphore == (SemaphoreInfo *) NULL)
727 memory_semaphore=AcquireSemaphoreInfo();
728 LockSemaphoreInfo(memory_semaphore);
729 UnlockSemaphoreInfo(memory_semaphore);
730 for (i=0; i < (ssize_t) memory_pool.number_segments; i++)
731 if (memory_pool.segments[i]->mapped == MagickFalse)
732 memory_methods.destroy_memory_handler(
733 memory_pool.segments[i]->allocation);
735 (void) UnmapBlob(memory_pool.segments[i]->allocation,
736 memory_pool.segments[i]->length);
737 free_segments=(DataSegmentInfo *) NULL;
738 (void) ResetMagickMemory(&memory_pool,0,sizeof(memory_pool));
739 RelinquishSemaphoreInfo(&memory_semaphore);
743 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
745 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
749 + E x p a n d H e a p %
753 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
755 % ExpandHeap() get more memory from the system. It returns MagickTrue on
756 % success otherwise MagickFalse.
758 % The format of the ExpandHeap method is:
760 % MagickBooleanType ExpandHeap(size_t size)
762 % A description of each parameter follows:
764 % o size: the size of the memory in bytes we require.
767 static MagickBooleanType ExpandHeap(size_t size)
787 blocksize=((size+12*sizeof(size_t))+SegmentSize-1) & -SegmentSize;
788 assert(memory_pool.number_segments < MaxSegments);
789 segment=MapBlob(-1,IOMode,0,blocksize);
790 mapped=segment != (void *) NULL ? MagickTrue : MagickFalse;
791 if (segment == (void *) NULL)
792 segment=(void *) memory_methods.acquire_memory_handler(blocksize);
793 if (segment == (void *) NULL)
795 segment_info=(DataSegmentInfo *) free_segments;
796 free_segments=segment_info->next;
797 segment_info->mapped=mapped;
798 segment_info->length=blocksize;
799 segment_info->allocation=segment;
800 segment_info->bound=(char *) segment+blocksize;
801 i=(ssize_t) memory_pool.number_segments-1;
802 for ( ; (i >= 0) && (memory_pool.segments[i]->allocation > segment); i--)
803 memory_pool.segments[i+1]=memory_pool.segments[i];
804 memory_pool.segments[i+1]=segment_info;
805 memory_pool.number_segments++;
806 size=blocksize-12*sizeof(size_t);
807 block=(char *) segment_info->allocation+4*sizeof(size_t);
808 *BlockHeader(block)=size | PreviousBlockBit;
809 *BlockFooter(block,size)=size;
810 InsertFreeBlock(block,AllocationPolicy(size));
811 block=NextBlock(block);
812 assert(block < segment_info->bound);
813 *BlockHeader(block)=2*sizeof(size_t);
814 *BlockHeader(NextBlock(block))=PreviousBlockBit;
820 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
824 % G e t M a g i c k M e m o r y M e t h o d s %
828 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
830 % GetMagickMemoryMethods() gets the methods to acquire, resize, and destroy
833 % The format of the GetMagickMemoryMethods() method is:
835 % void GetMagickMemoryMethods(AcquireMemoryHandler *acquire_memory_handler,
836 % ResizeMemoryHandler *resize_memory_handler,
837 % DestroyMemoryHandler *destroy_memory_handler)
839 % A description of each parameter follows:
841 % o acquire_memory_handler: method to acquire memory (e.g. malloc).
843 % o resize_memory_handler: method to resize memory (e.g. realloc).
845 % o destroy_memory_handler: method to destroy memory (e.g. free).
848 MagickExport void GetMagickMemoryMethods(
849 AcquireMemoryHandler *acquire_memory_handler,
850 ResizeMemoryHandler *resize_memory_handler,
851 DestroyMemoryHandler *destroy_memory_handler)
853 assert(acquire_memory_handler != (AcquireMemoryHandler *) NULL);
854 assert(resize_memory_handler != (ResizeMemoryHandler *) NULL);
855 assert(destroy_memory_handler != (DestroyMemoryHandler *) NULL);
856 *acquire_memory_handler=memory_methods.acquire_memory_handler;
857 *resize_memory_handler=memory_methods.resize_memory_handler;
858 *destroy_memory_handler=memory_methods.destroy_memory_handler;
862 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
866 % G e t V i r t u a l M e m o r y B l o b %
870 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
872 % GetVirtualMemoryBlob() returns the virtual memory blob associated with the
873 % specified MemoryInfo structure.
875 % The format of the GetVirtualMemoryBlob method is:
877 % void *GetVirtualMemoryBlob(const MemoryInfo *memory_info)
879 % A description of each parameter follows:
881 % o memory_info: The MemoryInfo structure.
883 MagickExport void *GetVirtualMemoryBlob(const MemoryInfo *memory_info)
885 assert(memory_info != (const MemoryInfo *) NULL);
886 assert(memory_info->signature == MagickSignature);
887 return(memory_info->blob);
891 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
895 % R e l i n q u i s h A l i g n e d M e m o r y %
899 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
901 % RelinquishAlignedMemory() frees memory acquired with AcquireAlignedMemory()
904 % The format of the RelinquishAlignedMemory method is:
906 % void *RelinquishAlignedMemory(void *memory)
908 % A description of each parameter follows:
910 % o memory: A pointer to a block of memory to free for reuse.
913 MagickExport void *RelinquishAlignedMemory(void *memory)
915 if (memory == (void *) NULL)
916 return((void *) NULL);
917 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
919 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
920 _aligned_free(memory);
922 free(*((void **) memory-1));
928 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
932 % R e l i n q u i s h M a g i c k M e m o r y %
936 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
938 % RelinquishMagickMemory() frees memory acquired with AcquireMagickMemory()
939 % or AcquireQuantumMemory() for reuse.
941 % The format of the RelinquishMagickMemory method is:
943 % void *RelinquishMagickMemory(void *memory)
945 % A description of each parameter follows:
947 % o memory: A pointer to a block of memory to free for reuse.
950 MagickExport void *RelinquishMagickMemory(void *memory)
952 if (memory == (void *) NULL)
953 return((void *) NULL);
954 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
955 memory_methods.destroy_memory_handler(memory);
957 LockSemaphoreInfo(memory_semaphore);
958 assert((SizeOfBlock(memory) % (4*sizeof(size_t))) == 0);
959 assert((*BlockHeader(NextBlock(memory)) & PreviousBlockBit) != 0);
960 if ((*BlockHeader(memory) & PreviousBlockBit) == 0)
966 Coalesce with previous adjacent block.
968 previous=PreviousBlock(memory);
969 RemoveFreeBlock(previous,AllocationPolicy(SizeOfBlock(previous)));
970 *BlockHeader(previous)=(SizeOfBlock(previous)+SizeOfBlock(memory)) |
971 (*BlockHeader(previous) & ~SizeMask);
974 if ((*BlockHeader(NextBlock(NextBlock(memory))) & PreviousBlockBit) == 0)
980 Coalesce with next adjacent block.
982 next=NextBlock(memory);
983 RemoveFreeBlock(next,AllocationPolicy(SizeOfBlock(next)));
984 *BlockHeader(memory)=(SizeOfBlock(memory)+SizeOfBlock(next)) |
985 (*BlockHeader(memory) & ~SizeMask);
987 *BlockFooter(memory,SizeOfBlock(memory))=SizeOfBlock(memory);
988 *BlockHeader(NextBlock(memory))&=(~PreviousBlockBit);
989 InsertFreeBlock(memory,AllocationPolicy(SizeOfBlock(memory)));
990 UnlockSemaphoreInfo(memory_semaphore);
992 return((void *) NULL);
996 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1000 % R e l i n q u i s h V i r t u a l M e m o r y %
1004 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1006 % RelinquishVirtualMemory() frees memory acquired with AcquireVirtualMemory().
1008 % The format of the RelinquishVirtualMemory method is:
1010 % MemoryInfo *RelinquishVirtualMemory(MemoryInfo *memory_info)
1012 % A description of each parameter follows:
1014 % o memory_info: A pointer to a block of memory to free for reuse.
1017 MagickExport MemoryInfo *RelinquishVirtualMemory(MemoryInfo *memory_info)
1019 assert(memory_info != (MemoryInfo *) NULL);
1020 assert(memory_info->signature == MagickSignature);
1021 if (memory_info->blob != (void *) NULL)
1022 switch (memory_info->type)
1024 case AlignedVirtualMemory:
1026 memory_info->blob=RelinquishAlignedMemory(memory_info->blob);
1027 RelinquishMagickResource(MemoryResource,memory_info->length);
1030 case MapVirtualMemory:
1032 (void) UnmapBlob(memory_info->blob,memory_info->length);
1033 memory_info->blob=NULL;
1034 RelinquishMagickResource(MapResource,memory_info->length);
1035 if (*memory_info->filename != '\0')
1036 (void) RelinquishUniqueFileResource(memory_info->filename);
1039 case UnalignedVirtualMemory:
1042 memory_info->blob=RelinquishMagickMemory(memory_info->blob);
1046 memory_info->signature=(~MagickSignature);
1047 memory_info=(MemoryInfo *) RelinquishAlignedMemory(memory_info);
1048 return(memory_info);
1052 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1056 % R e s e t M a g i c k M e m o r y %
1060 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1062 % ResetMagickMemory() fills the first size bytes of the memory area pointed to
1063 % by memory with the constant byte c.
1065 % The format of the ResetMagickMemory method is:
1067 % void *ResetMagickMemory(void *memory,int byte,const size_t size)
1069 % A description of each parameter follows:
1071 % o memory: a pointer to a memory allocation.
1073 % o byte: set the memory to this value.
1075 % o size: size of the memory to reset.
1078 MagickExport void *ResetMagickMemory(void *memory,int byte,const size_t size)
1080 assert(memory != (void *) NULL);
1081 return(memset(memory,byte,size));
1085 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1089 % R e s i z e M a g i c k M e m o r y %
1093 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1095 % ResizeMagickMemory() changes the size of the memory and returns a pointer to
1096 % the (possibly moved) block. The contents will be unchanged up to the
1097 % lesser of the new and old sizes.
1099 % The format of the ResizeMagickMemory method is:
1101 % void *ResizeMagickMemory(void *memory,const size_t size)
1103 % A description of each parameter follows:
1105 % o memory: A pointer to a memory allocation.
1107 % o size: the new size of the allocated memory.
1111 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
1112 static inline void *ResizeBlock(void *block,size_t size)
1117 if (block == (void *) NULL)
1118 return(AcquireBlock(size));
1119 memory=AcquireBlock(size);
1120 if (memory == (void *) NULL)
1121 return((void *) NULL);
1122 if (size <= (SizeOfBlock(block)-sizeof(size_t)))
1123 (void) memcpy(memory,block,size);
1125 (void) memcpy(memory,block,SizeOfBlock(block)-sizeof(size_t));
1126 memory_pool.allocation+=size;
1131 MagickExport void *ResizeMagickMemory(void *memory,const size_t size)
1136 if (memory == (void *) NULL)
1137 return(AcquireMagickMemory(size));
1138 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
1139 block=memory_methods.resize_memory_handler(memory,size == 0 ? 1UL : size);
1140 if (block == (void *) NULL)
1141 memory=RelinquishMagickMemory(memory);
1143 LockSemaphoreInfo(memory_semaphore);
1144 block=ResizeBlock(memory,size == 0 ? 1UL : size);
1145 if (block == (void *) NULL)
1147 if (ExpandHeap(size == 0 ? 1UL : size) == MagickFalse)
1149 UnlockSemaphoreInfo(memory_semaphore);
1150 memory=RelinquishMagickMemory(memory);
1151 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1153 block=ResizeBlock(memory,size == 0 ? 1UL : size);
1154 assert(block != (void *) NULL);
1156 UnlockSemaphoreInfo(memory_semaphore);
1157 memory=RelinquishMagickMemory(memory);
1163 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1167 % R e s i z e Q u a n t u m M e m o r y %
1171 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1173 % ResizeQuantumMemory() changes the size of the memory and returns a pointer
1174 % to the (possibly moved) block. The contents will be unchanged up to the
1175 % lesser of the new and old sizes.
1177 % The format of the ResizeQuantumMemory method is:
1179 % void *ResizeQuantumMemory(void *memory,const size_t count,
1180 % const size_t quantum)
1182 % A description of each parameter follows:
1184 % o memory: A pointer to a memory allocation.
1186 % o count: the number of quantum elements to allocate.
1188 % o quantum: the number of bytes in each quantum.
1191 MagickExport void *ResizeQuantumMemory(void *memory,const size_t count,
1192 const size_t quantum)
1198 if ((count == 0) || (quantum != (size/count)))
1200 memory=RelinquishMagickMemory(memory);
1202 return((void *) NULL);
1204 return(ResizeMagickMemory(memory,size));
1208 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1212 % S e t M a g i c k M e m o r y M e t h o d s %
1216 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1218 % SetMagickMemoryMethods() sets the methods to acquire, resize, and destroy
1219 % memory. Your custom memory methods must be set prior to the
1220 % MagickCoreGenesis() method.
1222 % The format of the SetMagickMemoryMethods() method is:
1224 % SetMagickMemoryMethods(AcquireMemoryHandler acquire_memory_handler,
1225 % ResizeMemoryHandler resize_memory_handler,
1226 % DestroyMemoryHandler destroy_memory_handler)
1228 % A description of each parameter follows:
1230 % o acquire_memory_handler: method to acquire memory (e.g. malloc).
1232 % o resize_memory_handler: method to resize memory (e.g. realloc).
1234 % o destroy_memory_handler: method to destroy memory (e.g. free).
1237 MagickExport void SetMagickMemoryMethods(
1238 AcquireMemoryHandler acquire_memory_handler,
1239 ResizeMemoryHandler resize_memory_handler,
1240 DestroyMemoryHandler destroy_memory_handler)
1245 if (acquire_memory_handler != (AcquireMemoryHandler) NULL)
1246 memory_methods.acquire_memory_handler=acquire_memory_handler;
1247 if (resize_memory_handler != (ResizeMemoryHandler) NULL)
1248 memory_methods.resize_memory_handler=resize_memory_handler;
1249 if (destroy_memory_handler != (DestroyMemoryHandler) NULL)
1250 memory_methods.destroy_memory_handler=destroy_memory_handler;