]> granicus.if.org Git - imagemagick/blob - MagickCore/memory.c
cleanup identical conditions (#1339)
[imagemagick] / MagickCore / memory.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
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                   %
11 %                                                                             %
12 %                                                                             %
13 %                     MagickCore Memory Allocation Methods                    %
14 %                                                                             %
15 %                              Software Design                                %
16 %                                   Cristy                                    %
17 %                                 July 1998                                   %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2018 ImageMagick Studio LLC, a non-profit organization      %
21 %  dedicated to making software imaging solutions freely available.           %
22 %                                                                             %
23 %  You may not use this file except in compliance with the License.  You may  %
24 %  obtain a copy of the License at                                            %
25 %                                                                             %
26 %    https://imagemagick.org/script/license.php                               %
27 %                                                                             %
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.                                             %
33 %                                                                             %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
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
38 %  memory corruption.
39 %
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.
45 %
46 %  By default, ANSI memory methods are called (e.g. malloc).  Use the
47 %  custom memory allocator by defining MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT
48 %  to allocate memory with private anonymous mapping rather than from the
49 %  heap.
50 %
51 */
52 \f
53 /*
54   Include declarations.
55 */
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/policy.h"
64 #include "MagickCore/resource_.h"
65 #include "MagickCore/semaphore.h"
66 #include "MagickCore/string_.h"
67 #include "MagickCore/string-private.h"
68 #include "MagickCore/utility-private.h"
69 \f
70 /*
71   Define declarations.
72 */
73 #define BlockFooter(block,size) \
74   ((size_t *) ((char *) (block)+(size)-2*sizeof(size_t)))
75 #define BlockHeader(block)  ((size_t *) (block)-1)
76 #define BlockSize  4096
77 #define BlockThreshold  1024
78 #define MaxBlockExponent  16
79 #define MaxBlocks ((BlockThreshold/(4*sizeof(size_t)))+MaxBlockExponent+1)
80 #define MaxSegments  1024
81 #define MemoryGuard  ((0xdeadbeef << 31)+0xdeafdeed)
82 #define NextBlock(block)  ((char *) (block)+SizeOfBlock(block))
83 #define NextBlockInList(block)  (*(void **) (block))
84 #define PreviousBlock(block)  ((char *) (block)-(*((size_t *) (block)-2)))
85 #define PreviousBlockBit  0x01
86 #define PreviousBlockInList(block)  (*((void **) (block)+1))
87 #define SegmentSize  (2*1024*1024)
88 #define SizeMask  (~0x01)
89 #define SizeOfBlock(block)  (*BlockHeader(block) & SizeMask)
90 \f
91 /*
92   Typedef declarations.
93 */
94 typedef enum
95 {
96   UndefinedVirtualMemory,
97   AlignedVirtualMemory,
98   MapVirtualMemory,
99   UnalignedVirtualMemory
100 } VirtualMemoryType;
101
102 typedef struct _DataSegmentInfo
103 {
104   void
105     *allocation,
106     *bound;
107
108   MagickBooleanType
109     mapped;
110
111   size_t
112     length;
113
114   struct _DataSegmentInfo
115     *previous,
116     *next;
117 } DataSegmentInfo;
118
119 typedef struct _MagickMemoryMethods
120 {
121   AcquireMemoryHandler
122     acquire_memory_handler;
123
124   ResizeMemoryHandler
125     resize_memory_handler;
126
127   DestroyMemoryHandler
128     destroy_memory_handler;
129 } MagickMemoryMethods;
130
131 struct _MemoryInfo
132 {
133   char
134     filename[MagickPathExtent];
135
136   VirtualMemoryType
137     type;
138
139   size_t
140     length;
141
142   void
143     *blob;
144
145   size_t
146     signature;
147 };
148
149 typedef struct _MemoryPool
150 {
151   size_t
152     allocation;
153
154   void
155     *blocks[MaxBlocks+1];
156
157   size_t
158     number_segments;
159
160   DataSegmentInfo
161     *segments[MaxSegments],
162     segment_pool[MaxSegments];
163 } MemoryPool;
164 \f
165 /*
166   Global declarations.
167 */
168 static size_t
169   max_memory_request = 0,
170   virtual_anonymous_memory = 0;
171
172 #if defined _MSC_VER
173 static void* MSCMalloc(size_t size)
174 {
175   return malloc(size);
176 }
177 static void* MSCRealloc(void* ptr, size_t size)
178 {
179   return realloc(ptr, size);
180 }
181 static void MSCFree(void* ptr)
182 {
183   free(ptr);
184 }
185 #endif
186
187 static MagickMemoryMethods
188   memory_methods =
189   {
190 #if defined _MSC_VER
191     (AcquireMemoryHandler) MSCMalloc,
192     (ResizeMemoryHandler) MSCRealloc,
193     (DestroyMemoryHandler) MSCFree
194 #else
195     (AcquireMemoryHandler) malloc,
196     (ResizeMemoryHandler) realloc,
197     (DestroyMemoryHandler) free
198 #endif
199   };
200 #if defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
201 static MemoryPool
202   memory_pool;
203
204 static SemaphoreInfo
205   *memory_semaphore = (SemaphoreInfo *) NULL;
206
207 static volatile DataSegmentInfo
208   *free_segments = (DataSegmentInfo *) NULL;
209 \f
210 /*
211   Forward declarations.
212 */
213 static MagickBooleanType
214   ExpandHeap(size_t);
215 #endif
216 \f
217 /*
218 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
219 %                                                                             %
220 %                                                                             %
221 %                                                                             %
222 %   A c q u i r e A l i g n e d M e m o r y                                   %
223 %                                                                             %
224 %                                                                             %
225 %                                                                             %
226 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
227 %
228 %  AcquireAlignedMemory() returns a pointer to a block of memory at least size
229 %  bytes whose address is aligned on a cache line or page boundary.
230 %
231 %  The format of the AcquireAlignedMemory method is:
232 %
233 %      void *AcquireAlignedMemory(const size_t count,const size_t quantum)
234 %
235 %  A description of each parameter follows:
236 %
237 %    o count: the number of quantum elements to allocate.
238 %
239 %    o quantum: the number of bytes in each quantum.
240 %
241 */
242 MagickExport void *AcquireAlignedMemory(const size_t count,const size_t quantum)
243 {
244 #define AlignedExtent(size,alignment) \
245   (((size)+((alignment)-1)) & ~((alignment)-1))
246
247   size_t
248     alignment,
249     extent,
250     size;
251
252   void
253     *memory;
254
255   if (HeapOverflowSanityCheck(count,quantum) != MagickFalse)
256     return((void *) NULL);
257   memory=NULL;
258   size=count*quantum;
259   alignment=CACHE_LINE_SIZE;
260   if (size > (size_t) (GetMagickPageSize() >> 1))
261     alignment=(size_t) GetMagickPageSize();
262   extent=AlignedExtent(size,CACHE_LINE_SIZE);
263   if ((size == 0) || (extent < size))
264     return((void *) NULL);
265 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
266   if (posix_memalign(&memory,alignment,extent) != 0)
267     memory=NULL;
268 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
269   memory=_aligned_malloc(extent,alignment);
270 #else
271   {
272     void
273       *p;
274
275     extent=(size+alignment-1)+sizeof(void *);
276     if (extent > size)
277       {
278         p=malloc(extent);
279         if (p != NULL)
280           {
281             memory=(void *) AlignedExtent((size_t) p+sizeof(void *),alignment);
282             *((void **) memory-1)=p;
283           }
284       }
285   }
286 #endif
287   return(memory);
288 }
289 \f
290 #if defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
291 /*
292 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
293 %                                                                             %
294 %                                                                             %
295 %                                                                             %
296 +   A c q u i r e B l o c k                                                   %
297 %                                                                             %
298 %                                                                             %
299 %                                                                             %
300 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
301 %
302 %  AcquireBlock() returns a pointer to a block of memory at least size bytes
303 %  suitably aligned for any use.
304 %
305 %  The format of the AcquireBlock method is:
306 %
307 %      void *AcquireBlock(const size_t size)
308 %
309 %  A description of each parameter follows:
310 %
311 %    o size: the size of the memory in bytes to allocate.
312 %
313 */
314
315 static inline size_t AllocationPolicy(size_t size)
316 {
317   register size_t
318     blocksize;
319
320   /*
321     The linear distribution.
322   */
323   assert(size != 0);
324   assert(size % (4*sizeof(size_t)) == 0);
325   if (size <= BlockThreshold)
326     return(size/(4*sizeof(size_t)));
327   /*
328     Check for the largest block size.
329   */
330   if (size > (size_t) (BlockThreshold*(1L << (MaxBlockExponent-1L))))
331     return(MaxBlocks-1L);
332   /*
333     Otherwise use a power of two distribution.
334   */
335   blocksize=BlockThreshold/(4*sizeof(size_t));
336   for ( ; size > BlockThreshold; size/=2)
337     blocksize++;
338   assert(blocksize > (BlockThreshold/(4*sizeof(size_t))));
339   assert(blocksize < (MaxBlocks-1L));
340   return(blocksize);
341 }
342
343 static inline void InsertFreeBlock(void *block,const size_t i)
344 {
345   register void
346     *next,
347     *previous;
348
349   size_t
350     size;
351
352   size=SizeOfBlock(block);
353   previous=(void *) NULL;
354   next=memory_pool.blocks[i];
355   while ((next != (void *) NULL) && (SizeOfBlock(next) < size))
356   {
357     previous=next;
358     next=NextBlockInList(next);
359   }
360   PreviousBlockInList(block)=previous;
361   NextBlockInList(block)=next;
362   if (previous != (void *) NULL)
363     NextBlockInList(previous)=block;
364   else
365     memory_pool.blocks[i]=block;
366   if (next != (void *) NULL)
367     PreviousBlockInList(next)=block;
368 }
369
370 static inline void RemoveFreeBlock(void *block,const size_t i)
371 {
372   register void
373     *next,
374     *previous;
375
376   next=NextBlockInList(block);
377   previous=PreviousBlockInList(block);
378   if (previous == (void *) NULL)
379     memory_pool.blocks[i]=next;
380   else
381     NextBlockInList(previous)=next;
382   if (next != (void *) NULL)
383     PreviousBlockInList(next)=previous;
384 }
385
386 static void *AcquireBlock(size_t size)
387 {
388   register size_t
389     i;
390
391   register void
392     *block;
393
394   /*
395     Find free block.
396   */
397   size=(size_t) (size+sizeof(size_t)+6*sizeof(size_t)-1) & -(4U*sizeof(size_t));
398   i=AllocationPolicy(size);
399   block=memory_pool.blocks[i];
400   while ((block != (void *) NULL) && (SizeOfBlock(block) < size))
401     block=NextBlockInList(block);
402   if (block == (void *) NULL)
403     {
404       i++;
405       while (memory_pool.blocks[i] == (void *) NULL)
406         i++;
407       block=memory_pool.blocks[i];
408       if (i >= MaxBlocks)
409         return((void *) NULL);
410     }
411   assert((*BlockHeader(NextBlock(block)) & PreviousBlockBit) == 0);
412   assert(SizeOfBlock(block) >= size);
413   RemoveFreeBlock(block,AllocationPolicy(SizeOfBlock(block)));
414   if (SizeOfBlock(block) > size)
415     {
416       size_t
417         blocksize;
418
419       void
420         *next;
421
422       /*
423         Split block.
424       */
425       next=(char *) block+size;
426       blocksize=SizeOfBlock(block)-size;
427       *BlockHeader(next)=blocksize;
428       *BlockFooter(next,blocksize)=blocksize;
429       InsertFreeBlock(next,AllocationPolicy(blocksize));
430       *BlockHeader(block)=size | (*BlockHeader(block) & ~SizeMask);
431     }
432   assert(size == SizeOfBlock(block));
433   *BlockHeader(NextBlock(block))|=PreviousBlockBit;
434   memory_pool.allocation+=size;
435   return(block);
436 }
437 #endif
438 \f
439 /*
440 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
441 %                                                                             %
442 %                                                                             %
443 %                                                                             %
444 %   A c q u i r e M a g i c k M e m o r y                                     %
445 %                                                                             %
446 %                                                                             %
447 %                                                                             %
448 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
449 %
450 %  AcquireMagickMemory() returns a pointer to a block of memory at least size
451 %  bytes suitably aligned for any use.
452 %
453 %  The format of the AcquireMagickMemory method is:
454 %
455 %      void *AcquireMagickMemory(const size_t size)
456 %
457 %  A description of each parameter follows:
458 %
459 %    o size: the size of the memory in bytes to allocate.
460 %
461 */
462 MagickExport void *AcquireMagickMemory(const size_t size)
463 {
464   register void
465     *memory;
466
467 #if !defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
468   memory=memory_methods.acquire_memory_handler(size == 0 ? 1UL : size);
469 #else
470   if (memory_semaphore == (SemaphoreInfo *) NULL)
471     ActivateSemaphoreInfo(&memory_semaphore);
472   if (free_segments == (DataSegmentInfo *) NULL)
473     {
474       LockSemaphoreInfo(memory_semaphore);
475       if (free_segments == (DataSegmentInfo *) NULL)
476         {
477           register ssize_t
478             i;
479
480           assert(2*sizeof(size_t) > (size_t) (~SizeMask));
481           (void) memset(&memory_pool,0,sizeof(memory_pool));
482           memory_pool.allocation=SegmentSize;
483           memory_pool.blocks[MaxBlocks]=(void *) (-1);
484           for (i=0; i < MaxSegments; i++)
485           {
486             if (i != 0)
487               memory_pool.segment_pool[i].previous=
488                 (&memory_pool.segment_pool[i-1]);
489             if (i != (MaxSegments-1))
490               memory_pool.segment_pool[i].next=(&memory_pool.segment_pool[i+1]);
491           }
492           free_segments=(&memory_pool.segment_pool[0]);
493         }
494       UnlockSemaphoreInfo(memory_semaphore);
495     }
496   LockSemaphoreInfo(memory_semaphore);
497   memory=AcquireBlock(size == 0 ? 1UL : size);
498   if (memory == (void *) NULL)
499     {
500       if (ExpandHeap(size == 0 ? 1UL : size) != MagickFalse)
501         memory=AcquireBlock(size == 0 ? 1UL : size);
502     }
503   UnlockSemaphoreInfo(memory_semaphore);
504 #endif
505   return(memory);
506 }
507 \f
508 /*
509 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
510 %                                                                             %
511 %                                                                             %
512 %                                                                             %
513 %   A c q u i r e Q u a n t u m M e m o r y                                   %
514 %                                                                             %
515 %                                                                             %
516 %                                                                             %
517 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
518 %
519 %  AcquireQuantumMemory() returns a pointer to a block of memory at least
520 %  count * quantum bytes suitably aligned for any use.
521 %
522 %  The format of the AcquireQuantumMemory method is:
523 %
524 %      void *AcquireQuantumMemory(const size_t count,const size_t quantum)
525 %
526 %  A description of each parameter follows:
527 %
528 %    o count: the number of quantum elements to allocate.
529 %
530 %    o quantum: the number of bytes in each quantum.
531 %
532 */
533 MagickExport void *AcquireQuantumMemory(const size_t count,const size_t quantum)
534 {
535   size_t
536     extent;
537
538   if (HeapOverflowSanityCheck(count,quantum) != MagickFalse)
539     return((void *) NULL);
540   extent=count*quantum;
541   return(AcquireMagickMemory(extent));
542 }
543 \f
544 /*
545 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
546 %                                                                             %
547 %                                                                             %
548 %                                                                             %
549 %   A c q u i r e V i r t u a l M e m o r y                                   %
550 %                                                                             %
551 %                                                                             %
552 %                                                                             %
553 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
554 %
555 %  AcquireVirtualMemory() allocates a pointer to a block of memory at least
556 %  size bytes suitably aligned for any use. In addition to heap, it also
557 %  supports memory-mapped and file-based memory-mapped memory requests.
558 %
559 %  The format of the AcquireVirtualMemory method is:
560 %
561 %      MemoryInfo *AcquireVirtualMemory(const size_t count,const size_t quantum)
562 %
563 %  A description of each parameter follows:
564 %
565 %    o count: the number of quantum elements to allocate.
566 %
567 %    o quantum: the number of bytes in each quantum.
568 %
569 */
570
571 MagickExport MemoryInfo *AcquireVirtualMemory(const size_t count,
572   const size_t quantum)
573 {
574   char
575     *value;
576
577   MemoryInfo
578     *memory_info;
579
580   size_t
581     extent;
582
583   if (HeapOverflowSanityCheck(count,quantum) != MagickFalse)
584     return((MemoryInfo *) NULL);
585   if (virtual_anonymous_memory == 0)
586     {
587       virtual_anonymous_memory=1;
588       value=GetPolicyValue("system:memory-map");
589       if (LocaleCompare(value,"anonymous") == 0)
590         {
591           /*
592             The security policy sets anonymous mapping for the memory request.
593           */
594 #if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
595           virtual_anonymous_memory=2;
596 #endif
597         }
598       value=DestroyString(value);
599     }
600   memory_info=(MemoryInfo *) MagickAssumeAligned(AcquireAlignedMemory(1,
601     sizeof(*memory_info)));
602   if (memory_info == (MemoryInfo *) NULL)
603     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
604   (void) memset(memory_info,0,sizeof(*memory_info));
605   extent=count*quantum;
606   memory_info->length=extent;
607   memory_info->signature=MagickCoreSignature;
608   if ((virtual_anonymous_memory == 1) &&
609       ((count*quantum) <= GetMaxMemoryRequest()))
610     {
611       memory_info->blob=AcquireAlignedMemory(1,extent);
612       if (memory_info->blob != NULL)
613         memory_info->type=AlignedVirtualMemory;
614     }
615   if (memory_info->blob == NULL)
616     {
617       /*
618         Acquire anonymous memory map.
619       */
620       memory_info->blob=NULL;
621       if ((count*quantum) <= GetMaxMemoryRequest())
622         memory_info->blob=MapBlob(-1,IOMode,0,extent);
623       if (memory_info->blob != NULL)
624         memory_info->type=MapVirtualMemory;
625       else
626         {
627           int
628             file;
629
630           /*
631             Anonymous memory mapping failed, try file-backed memory mapping.
632           */
633           file=AcquireUniqueFileResource(memory_info->filename);
634           if (file != -1)
635             {
636               MagickOffsetType
637                 offset;
638
639               offset=(MagickOffsetType) lseek(file,extent-1,SEEK_SET);
640               if ((offset == (MagickOffsetType) (extent-1)) &&
641                   (write(file,"",1) == 1))
642                 {
643                   memory_info->blob=MapBlob(file,IOMode,0,extent);
644                   if (memory_info->blob != NULL)
645                     memory_info->type=MapVirtualMemory;
646                   else
647                     {
648                       (void) RelinquishUniqueFileResource(
649                         memory_info->filename);
650                       *memory_info->filename='\0';
651                     }
652                 }
653               (void) close(file);
654             }
655         }
656     }
657   if (memory_info->blob == NULL)
658     {
659       memory_info->blob=AcquireQuantumMemory(1,extent);
660       if (memory_info->blob != NULL)
661         memory_info->type=UnalignedVirtualMemory;
662     }
663   if (memory_info->blob == NULL)
664     memory_info=RelinquishVirtualMemory(memory_info);
665   return(memory_info);
666 }
667 \f
668 /*
669 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
670 %                                                                             %
671 %                                                                             %
672 %                                                                             %
673 %   C o p y M a g i c k M e m o r y                                           %
674 %                                                                             %
675 %                                                                             %
676 %                                                                             %
677 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
678 %
679 %  CopyMagickMemory() copies size bytes from memory area source to the
680 %  destination.  Copying between objects that overlap will take place
681 %  correctly.  It returns destination.
682 %
683 %  The format of the CopyMagickMemory method is:
684 %
685 %      void *CopyMagickMemory(void *destination,const void *source,
686 %        const size_t size)
687 %
688 %  A description of each parameter follows:
689 %
690 %    o destination: the destination.
691 %
692 %    o source: the source.
693 %
694 %    o size: the size of the memory in bytes to allocate.
695 %
696 */
697 MagickExport void *CopyMagickMemory(void *destination,const void *source,
698   const size_t size)
699 {
700   register const unsigned char
701     *p;
702
703   register unsigned char
704     *q;
705
706   assert(destination != (void *) NULL);
707   assert(source != (const void *) NULL);
708   p=(const unsigned char *) source;
709   q=(unsigned char *) destination;
710   if (((q+size) < p) || (q > (p+size)))
711     switch (size)
712     {
713       default: return(memcpy(destination,source,size));
714       case 8: *q++=(*p++);
715       case 7: *q++=(*p++);
716       case 6: *q++=(*p++);
717       case 5: *q++=(*p++);
718       case 4: *q++=(*p++);
719       case 3: *q++=(*p++);
720       case 2: *q++=(*p++);
721       case 1: *q++=(*p++);
722       case 0: return(destination);
723     }
724   return(memmove(destination,source,size));
725 }
726 \f
727 /*
728 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
729 %                                                                             %
730 %                                                                             %
731 %                                                                             %
732 +   D e s t r o y M a g i c k M e m o r y                                     %
733 %                                                                             %
734 %                                                                             %
735 %                                                                             %
736 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
737 %
738 %  DestroyMagickMemory() deallocates memory associated with the memory manager.
739 %
740 %  The format of the DestroyMagickMemory method is:
741 %
742 %      DestroyMagickMemory(void)
743 %
744 */
745 MagickExport void DestroyMagickMemory(void)
746 {
747 #if defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
748   register ssize_t
749     i;
750
751   if (memory_semaphore == (SemaphoreInfo *) NULL)
752     ActivateSemaphoreInfo(&memory_semaphore);
753   LockSemaphoreInfo(memory_semaphore);
754   for (i=0; i < (ssize_t) memory_pool.number_segments; i++)
755     if (memory_pool.segments[i]->mapped == MagickFalse)
756       memory_methods.destroy_memory_handler(
757         memory_pool.segments[i]->allocation);
758     else
759       (void) UnmapBlob(memory_pool.segments[i]->allocation,
760         memory_pool.segments[i]->length);
761   free_segments=(DataSegmentInfo *) NULL;
762   (void) memset(&memory_pool,0,sizeof(memory_pool));
763   UnlockSemaphoreInfo(memory_semaphore);
764   RelinquishSemaphoreInfo(&memory_semaphore);
765 #endif
766 }
767 \f
768 #if defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
769 /*
770 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
771 %                                                                             %
772 %                                                                             %
773 %                                                                             %
774 +   E x p a n d H e a p                                                       %
775 %                                                                             %
776 %                                                                             %
777 %                                                                             %
778 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
779 %
780 %  ExpandHeap() get more memory from the system.  It returns MagickTrue on
781 %  success otherwise MagickFalse.
782 %
783 %  The format of the ExpandHeap method is:
784 %
785 %      MagickBooleanType ExpandHeap(size_t size)
786 %
787 %  A description of each parameter follows:
788 %
789 %    o size: the size of the memory in bytes we require.
790 %
791 */
792 static MagickBooleanType ExpandHeap(size_t size)
793 {
794   DataSegmentInfo
795     *segment_info;
796
797   MagickBooleanType
798     mapped;
799
800   register ssize_t
801     i;
802
803   register void
804     *block;
805
806   size_t
807     blocksize;
808
809   void
810     *segment;
811
812   blocksize=((size+12*sizeof(size_t))+SegmentSize-1) & -SegmentSize;
813   assert(memory_pool.number_segments < MaxSegments);
814   segment=MapBlob(-1,IOMode,0,blocksize);
815   mapped=segment != (void *) NULL ? MagickTrue : MagickFalse;
816   if (segment == (void *) NULL)
817     segment=(void *) memory_methods.acquire_memory_handler(blocksize);
818   if (segment == (void *) NULL)
819     return(MagickFalse);
820   segment_info=(DataSegmentInfo *) free_segments;
821   free_segments=segment_info->next;
822   segment_info->mapped=mapped;
823   segment_info->length=blocksize;
824   segment_info->allocation=segment;
825   segment_info->bound=(char *) segment+blocksize;
826   i=(ssize_t) memory_pool.number_segments-1;
827   for ( ; (i >= 0) && (memory_pool.segments[i]->allocation > segment); i--)
828     memory_pool.segments[i+1]=memory_pool.segments[i];
829   memory_pool.segments[i+1]=segment_info;
830   memory_pool.number_segments++;
831   size=blocksize-12*sizeof(size_t);
832   block=(char *) segment_info->allocation+4*sizeof(size_t);
833   *BlockHeader(block)=size | PreviousBlockBit;
834   *BlockFooter(block,size)=size;
835   InsertFreeBlock(block,AllocationPolicy(size));
836   block=NextBlock(block);
837   assert(block < segment_info->bound);
838   *BlockHeader(block)=2*sizeof(size_t);
839   *BlockHeader(NextBlock(block))=PreviousBlockBit;
840   return(MagickTrue);
841 }
842 #endif
843 \f
844 /*
845 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
846 %                                                                             %
847 %                                                                             %
848 %                                                                             %
849 %   G e t M a g i c k M e m o r y M e t h o d s                               %
850 %                                                                             %
851 %                                                                             %
852 %                                                                             %
853 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
854 %
855 %  GetMagickMemoryMethods() gets the methods to acquire, resize, and destroy
856 %  memory.
857 %
858 %  The format of the GetMagickMemoryMethods() method is:
859 %
860 %      void GetMagickMemoryMethods(AcquireMemoryHandler *acquire_memory_handler,
861 %        ResizeMemoryHandler *resize_memory_handler,
862 %        DestroyMemoryHandler *destroy_memory_handler)
863 %
864 %  A description of each parameter follows:
865 %
866 %    o acquire_memory_handler: method to acquire memory (e.g. malloc).
867 %
868 %    o resize_memory_handler: method to resize memory (e.g. realloc).
869 %
870 %    o destroy_memory_handler: method to destroy memory (e.g. free).
871 %
872 */
873 MagickExport void GetMagickMemoryMethods(
874   AcquireMemoryHandler *acquire_memory_handler,
875   ResizeMemoryHandler *resize_memory_handler,
876   DestroyMemoryHandler *destroy_memory_handler)
877 {
878   assert(acquire_memory_handler != (AcquireMemoryHandler *) NULL);
879   assert(resize_memory_handler != (ResizeMemoryHandler *) NULL);
880   assert(destroy_memory_handler != (DestroyMemoryHandler *) NULL);
881   *acquire_memory_handler=memory_methods.acquire_memory_handler;
882   *resize_memory_handler=memory_methods.resize_memory_handler;
883   *destroy_memory_handler=memory_methods.destroy_memory_handler;
884 }
885 \f
886 /*
887 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
888 %                                                                             %
889 %                                                                             %
890 %                                                                             %
891 +   G e t M a x M e m o r y R e q u e s t                                     %
892 %                                                                             %
893 %                                                                             %
894 %                                                                             %
895 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
896 %
897 %  GetMaxMemoryRequest() returns the max_memory_request value.
898 %
899 %  The format of the GetMaxMemoryRequest method is:
900 %
901 %      size_t GetMaxMemoryRequest(void)
902 %
903 */
904 MagickExport size_t GetMaxMemoryRequest(void)
905 {
906   if (max_memory_request == 0)
907     {
908       char
909         *value;
910
911       value=GetPolicyValue("system:max-memory-request");
912       if (value != (char *) NULL)
913         {
914           /*
915             The security policy sets a max memory request limit.
916           */
917           max_memory_request=StringToSizeType(value,100.0);
918           value=DestroyString(value);
919         }
920       else
921         max_memory_request=(size_t) MagickULLConstant(~0);
922     }
923   return(max_memory_request);
924 }
925 \f
926 /*
927 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
928 %                                                                             %
929 %                                                                             %
930 %                                                                             %
931 %   G e t V i r t u a l M e m o r y B l o b                                   %
932 %                                                                             %
933 %                                                                             %
934 %                                                                             %
935 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
936 %
937 %  GetVirtualMemoryBlob() returns the virtual memory blob associated with the
938 %  specified MemoryInfo structure.
939 %
940 %  The format of the GetVirtualMemoryBlob method is:
941 %
942 %      void *GetVirtualMemoryBlob(const MemoryInfo *memory_info)
943 %
944 %  A description of each parameter follows:
945 %
946 %    o memory_info: The MemoryInfo structure.
947 */
948 MagickExport void *GetVirtualMemoryBlob(const MemoryInfo *memory_info)
949 {
950   assert(memory_info != (const MemoryInfo *) NULL);
951   assert(memory_info->signature == MagickCoreSignature);
952   return(memory_info->blob);
953 }
954 \f
955 /*
956 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
957 %                                                                             %
958 %                                                                             %
959 %                                                                             %
960 +   H e a p O v e r f l o w S a n i t y C h e c k                             %
961 %                                                                             %
962 %                                                                             %
963 %                                                                             %
964 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
965 %
966 %  HeapOverflowSanityCheck() returns MagickTrue if the heap allocation request
967 %  does not exceed the maximum limits of a size_t otherwise MagickFalse.
968 %
969 %  The format of the HeapOverflowSanityCheck method is:
970 %
971 %      MagickBooleanType HeapOverflowSanityCheck(const size_t count,
972 %        const size_t quantum)
973 %
974 %  A description of each parameter follows:
975 %
976 %    o size: the size of the memory in bytes we require.
977 %
978 */
979 MagickExport MagickBooleanType HeapOverflowSanityCheck(const size_t count,
980   const size_t quantum)
981 {
982   size_t
983     size;
984
985   size=count*quantum;
986   if ((count == 0) || (quantum != (size/count)))
987     {
988       errno=ENOMEM;
989       return(MagickTrue);
990     }
991   return(MagickFalse);
992 }
993 \f
994 /*
995 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
996 %                                                                             %
997 %                                                                             %
998 %                                                                             %
999 %   R e l i n q u i s h A l i g n e d M e m o r y                             %
1000 %                                                                             %
1001 %                                                                             %
1002 %                                                                             %
1003 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1004 %
1005 %  RelinquishAlignedMemory() frees memory acquired with AcquireAlignedMemory()
1006 %  or reuse.
1007 %
1008 %  The format of the RelinquishAlignedMemory method is:
1009 %
1010 %      void *RelinquishAlignedMemory(void *memory)
1011 %
1012 %  A description of each parameter follows:
1013 %
1014 %    o memory: A pointer to a block of memory to free for reuse.
1015 %
1016 */
1017 MagickExport void *RelinquishAlignedMemory(void *memory)
1018 {
1019   if (memory == (void *) NULL)
1020     return((void *) NULL);
1021 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
1022   free(memory);
1023 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
1024   _aligned_free(memory);
1025 #else
1026   free(*((void **) memory-1));
1027 #endif
1028   return(NULL);
1029 }
1030 \f
1031 /*
1032 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1033 %                                                                             %
1034 %                                                                             %
1035 %                                                                             %
1036 %   R e l i n q u i s h M a g i c k M e m o r y                               %
1037 %                                                                             %
1038 %                                                                             %
1039 %                                                                             %
1040 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1041 %
1042 %  RelinquishMagickMemory() frees memory acquired with AcquireMagickMemory()
1043 %  or AcquireQuantumMemory() for reuse.
1044 %
1045 %  The format of the RelinquishMagickMemory method is:
1046 %
1047 %      void *RelinquishMagickMemory(void *memory)
1048 %
1049 %  A description of each parameter follows:
1050 %
1051 %    o memory: A pointer to a block of memory to free for reuse.
1052 %
1053 */
1054 MagickExport void *RelinquishMagickMemory(void *memory)
1055 {
1056   if (memory == (void *) NULL)
1057     return((void *) NULL);
1058 #if !defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
1059   memory_methods.destroy_memory_handler(memory);
1060 #else
1061   LockSemaphoreInfo(memory_semaphore);
1062   assert((SizeOfBlock(memory) % (4*sizeof(size_t))) == 0);
1063   assert((*BlockHeader(NextBlock(memory)) & PreviousBlockBit) != 0);
1064   if ((*BlockHeader(memory) & PreviousBlockBit) == 0)
1065     {
1066       void
1067         *previous;
1068
1069       /*
1070         Coalesce with previous adjacent block.
1071       */
1072       previous=PreviousBlock(memory);
1073       RemoveFreeBlock(previous,AllocationPolicy(SizeOfBlock(previous)));
1074       *BlockHeader(previous)=(SizeOfBlock(previous)+SizeOfBlock(memory)) |
1075         (*BlockHeader(previous) & ~SizeMask);
1076       memory=previous;
1077     }
1078   if ((*BlockHeader(NextBlock(NextBlock(memory))) & PreviousBlockBit) == 0)
1079     {
1080       void
1081         *next;
1082
1083       /*
1084         Coalesce with next adjacent block.
1085       */
1086       next=NextBlock(memory);
1087       RemoveFreeBlock(next,AllocationPolicy(SizeOfBlock(next)));
1088       *BlockHeader(memory)=(SizeOfBlock(memory)+SizeOfBlock(next)) |
1089         (*BlockHeader(memory) & ~SizeMask);
1090     }
1091   *BlockFooter(memory,SizeOfBlock(memory))=SizeOfBlock(memory);
1092   *BlockHeader(NextBlock(memory))&=(~PreviousBlockBit);
1093   InsertFreeBlock(memory,AllocationPolicy(SizeOfBlock(memory)));
1094   UnlockSemaphoreInfo(memory_semaphore);
1095 #endif
1096   return((void *) NULL);
1097 }
1098 \f
1099 /*
1100 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1101 %                                                                             %
1102 %                                                                             %
1103 %                                                                             %
1104 %   R e l i n q u i s h V i r t u a l M e m o r y                             %
1105 %                                                                             %
1106 %                                                                             %
1107 %                                                                             %
1108 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1109 %
1110 %  RelinquishVirtualMemory() frees memory acquired with AcquireVirtualMemory().
1111 %
1112 %  The format of the RelinquishVirtualMemory method is:
1113 %
1114 %      MemoryInfo *RelinquishVirtualMemory(MemoryInfo *memory_info)
1115 %
1116 %  A description of each parameter follows:
1117 %
1118 %    o memory_info: A pointer to a block of memory to free for reuse.
1119 %
1120 */
1121 MagickExport MemoryInfo *RelinquishVirtualMemory(MemoryInfo *memory_info)
1122 {
1123   assert(memory_info != (MemoryInfo *) NULL);
1124   assert(memory_info->signature == MagickCoreSignature);
1125   if (memory_info->blob != (void *) NULL)
1126     switch (memory_info->type)
1127     {
1128       case AlignedVirtualMemory:
1129       {
1130         memory_info->blob=RelinquishAlignedMemory(memory_info->blob);
1131         break;
1132       }
1133       case MapVirtualMemory:
1134       {
1135         (void) UnmapBlob(memory_info->blob,memory_info->length);
1136         memory_info->blob=NULL;
1137         if (*memory_info->filename != '\0')
1138           (void) RelinquishUniqueFileResource(memory_info->filename);
1139         break;
1140       }
1141       case UnalignedVirtualMemory:
1142       default:
1143       {
1144         memory_info->blob=RelinquishMagickMemory(memory_info->blob);
1145         break;
1146       }
1147     }
1148   memory_info->signature=(~MagickCoreSignature);
1149   memory_info=(MemoryInfo *) RelinquishAlignedMemory(memory_info);
1150   return(memory_info);
1151 }
1152 \f
1153 /*
1154 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1155 %                                                                             %
1156 %                                                                             %
1157 %                                                                             %
1158 %   R e s e t M a g i c k M e m o r y                                         %
1159 %                                                                             %
1160 %                                                                             %
1161 %                                                                             %
1162 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1163 %
1164 %  ResetMagickMemory() fills the first size bytes of the memory area pointed to
1165 %  by memory with the constant byte c.
1166 %
1167 %  The format of the ResetMagickMemory method is:
1168 %
1169 %      void *ResetMagickMemory(void *memory,int byte,const size_t size)
1170 %
1171 %  A description of each parameter follows:
1172 %
1173 %    o memory: a pointer to a memory allocation.
1174 %
1175 %    o byte: set the memory to this value.
1176 %
1177 %    o size: size of the memory to reset.
1178 %
1179 */
1180 MagickExport void *ResetMagickMemory(void *memory,int byte,const size_t size)
1181 {
1182   assert(memory != (void *) NULL);
1183   return(memset(memory,byte,size));
1184 }
1185 \f
1186 /*
1187 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1188 %                                                                             %
1189 %                                                                             %
1190 %                                                                             %
1191 +   R e s e t M a x M e m o r y R e q u e s t                                 %
1192 %                                                                             %
1193 %                                                                             %
1194 %                                                                             %
1195 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1196 %
1197 %  ResetMaxMemoryRequest() resets the max_memory_request value.
1198 %
1199 %  The format of the ResetMaxMemoryRequest method is:
1200 %
1201 %      void ResetMaxMemoryRequest(void)
1202 %
1203 */
1204 MagickPrivate void ResetMaxMemoryRequest(void)
1205 {
1206   max_memory_request=0;
1207 }
1208 \f
1209 /*
1210 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1211 %                                                                             %
1212 %                                                                             %
1213 %                                                                             %
1214 +   R e s e t V i r t u a l A n o n y m o u s M e m o r y                     %
1215 %                                                                             %
1216 %                                                                             %
1217 %                                                                             %
1218 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1219 %
1220 %  ResetVirtualAnonymousMemory() resets the virtual_anonymous_memory value.
1221 %
1222 %  The format of the ResetVirtualAnonymousMemory method is:
1223 %
1224 %      void ResetVirtualAnonymousMemory(void)
1225 %
1226 */
1227 MagickPrivate void ResetVirtualAnonymousMemory(void)
1228 {
1229   virtual_anonymous_memory=0;
1230 }
1231 \f
1232 /*
1233 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1234 %                                                                             %
1235 %                                                                             %
1236 %                                                                             %
1237 %   R e s i z e M a g i c k M e m o r y                                       %
1238 %                                                                             %
1239 %                                                                             %
1240 %                                                                             %
1241 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1242 %
1243 %  ResizeMagickMemory() changes the size of the memory and returns a pointer to
1244 %  the (possibly moved) block.  The contents will be unchanged up to the
1245 %  lesser of the new and old sizes.
1246 %
1247 %  The format of the ResizeMagickMemory method is:
1248 %
1249 %      void *ResizeMagickMemory(void *memory,const size_t size)
1250 %
1251 %  A description of each parameter follows:
1252 %
1253 %    o memory: A pointer to a memory allocation.
1254 %
1255 %    o size: the new size of the allocated memory.
1256 %
1257 */
1258
1259 #if defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
1260 static inline void *ResizeBlock(void *block,size_t size)
1261 {
1262   register void
1263     *memory;
1264
1265   if (block == (void *) NULL)
1266     return(AcquireBlock(size));
1267   memory=AcquireBlock(size);
1268   if (memory == (void *) NULL)
1269     return((void *) NULL);
1270   if (size <= (SizeOfBlock(block)-sizeof(size_t)))
1271     (void) memcpy(memory,block,size);
1272   else
1273     (void) memcpy(memory,block,SizeOfBlock(block)-sizeof(size_t));
1274   memory_pool.allocation+=size;
1275   return(memory);
1276 }
1277 #endif
1278
1279 MagickExport void *ResizeMagickMemory(void *memory,const size_t size)
1280 {
1281   register void
1282     *block;
1283
1284   if (memory == (void *) NULL)
1285     return(AcquireMagickMemory(size));
1286 #if !defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
1287   block=memory_methods.resize_memory_handler(memory,size == 0 ? 1UL : size);
1288   if (block == (void *) NULL)
1289     memory=RelinquishMagickMemory(memory);
1290 #else
1291   LockSemaphoreInfo(memory_semaphore);
1292   block=ResizeBlock(memory,size == 0 ? 1UL : size);
1293   if (block == (void *) NULL)
1294     {
1295       if (ExpandHeap(size == 0 ? 1UL : size) == MagickFalse)
1296         {
1297           UnlockSemaphoreInfo(memory_semaphore);
1298           memory=RelinquishMagickMemory(memory);
1299           ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1300         }
1301       block=ResizeBlock(memory,size == 0 ? 1UL : size);
1302       assert(block != (void *) NULL);
1303     }
1304   UnlockSemaphoreInfo(memory_semaphore);
1305   memory=RelinquishMagickMemory(memory);
1306 #endif
1307   return(block);
1308 }
1309 \f
1310 /*
1311 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1312 %                                                                             %
1313 %                                                                             %
1314 %                                                                             %
1315 %   R e s i z e Q u a n t u m M e m o r y                                     %
1316 %                                                                             %
1317 %                                                                             %
1318 %                                                                             %
1319 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1320 %
1321 %  ResizeQuantumMemory() changes the size of the memory and returns a pointer
1322 %  to the (possibly moved) block.  The contents will be unchanged up to the
1323 %  lesser of the new and old sizes.
1324 %
1325 %  The format of the ResizeQuantumMemory method is:
1326 %
1327 %      void *ResizeQuantumMemory(void *memory,const size_t count,
1328 %        const size_t quantum)
1329 %
1330 %  A description of each parameter follows:
1331 %
1332 %    o memory: A pointer to a memory allocation.
1333 %
1334 %    o count: the number of quantum elements to allocate.
1335 %
1336 %    o quantum: the number of bytes in each quantum.
1337 %
1338 */
1339 MagickExport void *ResizeQuantumMemory(void *memory,const size_t count,
1340   const size_t quantum)
1341 {
1342   size_t
1343     extent;
1344
1345   if (HeapOverflowSanityCheck(count,quantum) != MagickFalse)
1346     {
1347       memory=RelinquishMagickMemory(memory);
1348       return((void *) NULL);
1349     }
1350   extent=count*quantum;
1351   return(ResizeMagickMemory(memory,extent));
1352 }
1353 \f
1354 /*
1355 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1356 %                                                                             %
1357 %                                                                             %
1358 %                                                                             %
1359 %   S e t M a g i c k M e m o r y M e t h o d s                               %
1360 %                                                                             %
1361 %                                                                             %
1362 %                                                                             %
1363 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1364 %
1365 %  SetMagickMemoryMethods() sets the methods to acquire, resize, and destroy
1366 %  memory. Your custom memory methods must be set prior to the
1367 %  MagickCoreGenesis() method.
1368 %
1369 %  The format of the SetMagickMemoryMethods() method is:
1370 %
1371 %      SetMagickMemoryMethods(AcquireMemoryHandler acquire_memory_handler,
1372 %        ResizeMemoryHandler resize_memory_handler,
1373 %        DestroyMemoryHandler destroy_memory_handler)
1374 %
1375 %  A description of each parameter follows:
1376 %
1377 %    o acquire_memory_handler: method to acquire memory (e.g. malloc).
1378 %
1379 %    o resize_memory_handler: method to resize memory (e.g. realloc).
1380 %
1381 %    o destroy_memory_handler: method to destroy memory (e.g. free).
1382 %
1383 */
1384 MagickExport void SetMagickMemoryMethods(
1385   AcquireMemoryHandler acquire_memory_handler,
1386   ResizeMemoryHandler resize_memory_handler,
1387   DestroyMemoryHandler destroy_memory_handler)
1388 {
1389   /*
1390     Set memory methods.
1391   */
1392   if (acquire_memory_handler != (AcquireMemoryHandler) NULL)
1393     memory_methods.acquire_memory_handler=acquire_memory_handler;
1394   if (resize_memory_handler != (ResizeMemoryHandler) NULL)
1395     memory_methods.resize_memory_handler=resize_memory_handler;
1396   if (destroy_memory_handler != (DestroyMemoryHandler) NULL)
1397     memory_methods.destroy_memory_handler=destroy_memory_handler;
1398 }