]> granicus.if.org Git - imagemagick/blob - MagickCore/memory.c
(no commit message)
[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-2014 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 %    http://www.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_ZERO_CONFIGURATION_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/resource_.h"
64 #include "MagickCore/semaphore.h"
65 #include "MagickCore/string_.h"
66 #include "MagickCore/utility-private.h"
67 \f
68 /*
69   Define declarations.
70 */
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)
88 \f
89 /*
90   Typedef declarations.
91 */
92 typedef enum
93 {
94   UndefinedVirtualMemory,
95   AlignedVirtualMemory,
96   MapVirtualMemory,
97   UnalignedVirtualMemory
98 } VirtualMemoryType;
99
100 typedef struct _DataSegmentInfo
101 {
102   void
103     *allocation,
104     *bound;
105
106   MagickBooleanType
107     mapped;
108
109   size_t
110     length;
111
112   struct _DataSegmentInfo
113     *previous,
114     *next;
115 } DataSegmentInfo;
116
117 typedef struct _MagickMemoryMethods
118 {
119   AcquireMemoryHandler
120     acquire_memory_handler;
121
122   ResizeMemoryHandler
123     resize_memory_handler;
124
125   DestroyMemoryHandler
126     destroy_memory_handler;
127 } MagickMemoryMethods;
128
129 struct _MemoryInfo
130 {
131   char
132     filename[MaxTextExtent];
133
134   VirtualMemoryType
135     type;
136
137   size_t
138     length;
139
140   void
141     *blob;
142
143   size_t
144     signature;
145 };
146
147 typedef struct _MemoryPool
148 {
149   size_t
150     allocation;
151
152   void
153     *blocks[MaxBlocks+1];
154
155   size_t
156     number_segments;
157
158   DataSegmentInfo
159     *segments[MaxSegments],
160     segment_pool[MaxSegments];
161 } MemoryPool;
162 \f
163 /*
164   Global declarations.
165 */
166 #if defined _MSC_VER
167 static void* MSCMalloc(size_t size)
168 {
169   return malloc(size);
170 }
171 static void* MSCRealloc(void* ptr, size_t size)
172 {
173   return realloc(ptr, size);
174 }
175 static void MSCFree(void* ptr)
176 {
177   free(ptr);
178 }
179 #endif
180
181 static MagickMemoryMethods
182   memory_methods =
183   {
184 #if defined _MSC_VER
185     (AcquireMemoryHandler) MSCMalloc,
186     (ResizeMemoryHandler) MSCRealloc,
187     (DestroyMemoryHandler) MSCFree
188 #else
189     (AcquireMemoryHandler) malloc,
190     (ResizeMemoryHandler) realloc,
191     (DestroyMemoryHandler) free
192 #endif
193   };
194 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
195 static MemoryPool
196   memory_pool;
197
198 static SemaphoreInfo
199   *memory_semaphore = (SemaphoreInfo *) NULL;
200
201 static volatile DataSegmentInfo
202   *free_segments = (DataSegmentInfo *) NULL;
203 \f
204 /*
205   Forward declarations.
206 */
207 static MagickBooleanType
208   ExpandHeap(size_t);
209 #endif
210 \f
211 /*
212 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
213 %                                                                             %
214 %                                                                             %
215 %                                                                             %
216 %   A c q u i r e A l i g n e d M e m o r y                                   %
217 %                                                                             %
218 %                                                                             %
219 %                                                                             %
220 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
221 %
222 %  AcquireAlignedMemory() returns a pointer to a block of memory at least size
223 %  bytes whose address is a multiple of 16*sizeof(void *).
224 %
225 %  The format of the AcquireAlignedMemory method is:
226 %
227 %      void *AcquireAlignedMemory(const size_t count,const size_t quantum)
228 %
229 %  A description of each parameter follows:
230 %
231 %    o count: the number of quantum elements to allocate.
232 %
233 %    o quantum: the number of bytes in each quantum.
234 %
235 */
236 MagickExport void *AcquireAlignedMemory(const size_t count,const size_t quantum)
237 {
238 #define AlignedExtent(size,alignment) \
239   (((size)+((alignment)-1)) & ~((alignment)-1))
240
241   size_t
242     alignment,
243     extent,
244     size;
245
246   void
247     *memory;
248
249   size=count*quantum;
250   if ((count == 0) || (quantum != (size/count)))
251     {
252       errno=ENOMEM;
253       return((void *) NULL);
254     }
255   memory=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)
262     memory=NULL;
263 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
264   memory=_aligned_malloc(extent,alignment);
265 #else
266   {
267     void
268       *p;
269
270     extent=(size+alignment-1)+sizeof(void *);
271     if (extent > size)
272       {
273         p=malloc(extent);
274         if (p != NULL)
275           {
276             memory=(void *) AlignedExtent((size_t) p+sizeof(void *),alignment);
277             *((void **) memory-1)=p;
278           }
279       }
280   }
281 #endif
282   return(memory);
283 }
284 \f
285 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
286 /*
287 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
288 %                                                                             %
289 %                                                                             %
290 %                                                                             %
291 +   A c q u i r e B l o c k                                                   %
292 %                                                                             %
293 %                                                                             %
294 %                                                                             %
295 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
296 %
297 %  AcquireBlock() returns a pointer to a block of memory at least size bytes
298 %  suitably aligned for any use.
299 %
300 %  The format of the AcquireBlock method is:
301 %
302 %      void *AcquireBlock(const size_t size)
303 %
304 %  A description of each parameter follows:
305 %
306 %    o size: the size of the memory in bytes to allocate.
307 %
308 */
309
310 static inline size_t AllocationPolicy(size_t size)
311 {
312   register size_t
313     blocksize;
314
315   /*
316     The linear distribution.
317   */
318   assert(size != 0);
319   assert(size % (4*sizeof(size_t)) == 0);
320   if (size <= BlockThreshold)
321     return(size/(4*sizeof(size_t)));
322   /*
323     Check for the largest block size.
324   */
325   if (size > (size_t) (BlockThreshold*(1L << (MaxBlockExponent-1L))))
326     return(MaxBlocks-1L);
327   /*
328     Otherwise use a power of two distribution.
329   */
330   blocksize=BlockThreshold/(4*sizeof(size_t));
331   for ( ; size > BlockThreshold; size/=2)
332     blocksize++;
333   assert(blocksize > (BlockThreshold/(4*sizeof(size_t))));
334   assert(blocksize < (MaxBlocks-1L));
335   return(blocksize);
336 }
337
338 static inline void InsertFreeBlock(void *block,const size_t i)
339 {
340   register void
341     *next,
342     *previous;
343
344   size_t
345     size;
346
347   size=SizeOfBlock(block);
348   previous=(void *) NULL;
349   next=memory_pool.blocks[i];
350   while ((next != (void *) NULL) && (SizeOfBlock(next) < size))
351   {
352     previous=next;
353     next=NextBlockInList(next);
354   }
355   PreviousBlockInList(block)=previous;
356   NextBlockInList(block)=next;
357   if (previous != (void *) NULL)
358     NextBlockInList(previous)=block;
359   else
360     memory_pool.blocks[i]=block;
361   if (next != (void *) NULL)
362     PreviousBlockInList(next)=block;
363 }
364
365 static inline void RemoveFreeBlock(void *block,const size_t i)
366 {
367   register void
368     *next,
369     *previous;
370
371   next=NextBlockInList(block);
372   previous=PreviousBlockInList(block);
373   if (previous == (void *) NULL)
374     memory_pool.blocks[i]=next;
375   else
376     NextBlockInList(previous)=next;
377   if (next != (void *) NULL)
378     PreviousBlockInList(next)=previous;
379 }
380
381 static void *AcquireBlock(size_t size)
382 {
383   register size_t
384     i;
385
386   register void
387     *block;
388
389   /*
390     Find free block.
391   */
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)
398     {
399       i++;
400       while (memory_pool.blocks[i] == (void *) NULL)
401         i++;
402       block=memory_pool.blocks[i];
403       if (i >= MaxBlocks)
404         return((void *) NULL);
405     }
406   assert((*BlockHeader(NextBlock(block)) & PreviousBlockBit) == 0);
407   assert(SizeOfBlock(block) >= size);
408   RemoveFreeBlock(block,AllocationPolicy(SizeOfBlock(block)));
409   if (SizeOfBlock(block) > size)
410     {
411       size_t
412         blocksize;
413
414       void
415         *next;
416
417       /*
418         Split block.
419       */
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);
426     }
427   assert(size == SizeOfBlock(block));
428   *BlockHeader(NextBlock(block))|=PreviousBlockBit;
429   memory_pool.allocation+=size;
430   return(block);
431 }
432 #endif
433 \f
434 /*
435 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
436 %                                                                             %
437 %                                                                             %
438 %                                                                             %
439 %   A c q u i r e M a g i c k M e m o r y                                     %
440 %                                                                             %
441 %                                                                             %
442 %                                                                             %
443 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
444 %
445 %  AcquireMagickMemory() returns a pointer to a block of memory at least size
446 %  bytes suitably aligned for any use.
447 %
448 %  The format of the AcquireMagickMemory method is:
449 %
450 %      void *AcquireMagickMemory(const size_t size)
451 %
452 %  A description of each parameter follows:
453 %
454 %    o size: the size of the memory in bytes to allocate.
455 %
456 */
457 MagickExport void *AcquireMagickMemory(const size_t size)
458 {
459   register void
460     *memory;
461
462 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
463   memory=memory_methods.acquire_memory_handler(size == 0 ? 1UL : size);
464 #else
465   if (memory_semaphore == (SemaphoreInfo *) NULL)
466     memory_semaphore=AcquireSemaphoreInfo();
467   if (free_segments == (DataSegmentInfo *) NULL)
468     {
469       LockSemaphoreInfo(memory_semaphore);
470       if (free_segments == (DataSegmentInfo *) NULL)
471         {
472           register ssize_t
473             i;
474
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++)
480           {
481             if (i != 0)
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]);
486           }
487           free_segments=(&memory_pool.segment_pool[0]);
488         }
489       UnlockSemaphoreInfo(memory_semaphore);
490     }
491   LockSemaphoreInfo(memory_semaphore);
492   memory=AcquireBlock(size == 0 ? 1UL : size);
493   if (memory == (void *) NULL)
494     {
495       if (ExpandHeap(size == 0 ? 1UL : size) != MagickFalse)
496         memory=AcquireBlock(size == 0 ? 1UL : size);
497     }
498   UnlockSemaphoreInfo(memory_semaphore);
499 #endif
500   return(memory);
501 }
502 \f
503 /*
504 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
505 %                                                                             %
506 %                                                                             %
507 %                                                                             %
508 %   A c q u i r e Q u a n t u m M e m o r y                                   %
509 %                                                                             %
510 %                                                                             %
511 %                                                                             %
512 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
513 %
514 %  AcquireQuantumMemory() returns a pointer to a block of memory at least
515 %  count * quantum bytes suitably aligned for any use.
516 %
517 %  The format of the AcquireQuantumMemory method is:
518 %
519 %      void *AcquireQuantumMemory(const size_t count,const size_t quantum)
520 %
521 %  A description of each parameter follows:
522 %
523 %    o count: the number of quantum elements to allocate.
524 %
525 %    o quantum: the number of bytes in each quantum.
526 %
527 */
528 MagickExport void *AcquireQuantumMemory(const size_t count,const size_t quantum)
529 {
530   size_t
531     size;
532
533   size=count*quantum;
534   if ((count == 0) || (quantum != (size/count)))
535     {
536       errno=ENOMEM;
537       return((void *) NULL);
538     }
539   return(AcquireMagickMemory(size));
540 }
541 \f
542 /*
543 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
544 %                                                                             %
545 %                                                                             %
546 %                                                                             %
547 %   A c q u i r e V i r t u a l M e m o r y                                   %
548 %                                                                             %
549 %                                                                             %
550 %                                                                             %
551 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
552 %
553 %  AcquireVirtualMemory() allocates a pointer to a block of memory at least size
554 %  bytes suitably aligned for any use.
555 %
556 %  The format of the AcquireVirtualMemory method is:
557 %
558 %      MemoryInfo *AcquireVirtualMemory(const size_t count,const size_t quantum)
559 %
560 %  A description of each parameter follows:
561 %
562 %    o count: the number of quantum elements to allocate.
563 %
564 %    o quantum: the number of bytes in each quantum.
565 %
566 */
567 MagickExport MemoryInfo *AcquireVirtualMemory(const size_t count,
568   const size_t quantum)
569 {
570   MemoryInfo
571     *memory_info;
572
573   size_t
574     length;
575
576   length=count*quantum;
577   if ((count == 0) || (quantum != (length/count)))
578     {
579       errno=ENOMEM;
580       return((MemoryInfo *) NULL);
581     }
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)
590     {
591       memory_info->blob=AcquireAlignedMemory(1,length);
592       if (memory_info->blob != NULL)
593         memory_info->type=AlignedVirtualMemory;
594       else
595         RelinquishMagickResource(MemoryResource,length);
596     }
597   if ((memory_info->blob == NULL) &&
598       (AcquireMagickResource(MapResource,length) != MagickFalse))
599     {
600       /*
601         Heap memory failed, try anonymous memory mapping.
602       */
603       memory_info->blob=MapBlob(-1,IOMode,0,length);
604       if (memory_info->blob != NULL)
605         memory_info->type=MapVirtualMemory;
606       else
607         RelinquishMagickResource(MapResource,length);
608     }
609   if (memory_info->blob == NULL)
610     {
611       int
612         file;
613
614       /*
615         Anonymous memory mapping failed, try file-backed memory mapping.
616       */
617       file=AcquireUniqueFileResource(memory_info->filename);
618       if (file != -1)
619         {
620           if ((lseek(file,length-1,SEEK_SET) >= 0) && (write(file,"",1) == 1))
621             {
622               memory_info->blob=MapBlob(file,IOMode,0,length);
623               if (memory_info->blob != NULL)
624                 {
625                   memory_info->type=MapVirtualMemory;
626                   (void) AcquireMagickResource(MapResource,length);
627                 }
628             }
629           (void) close(file);
630         }
631     }
632   if (memory_info->blob == NULL)
633     {
634       memory_info->blob=AcquireMagickMemory(length);
635       if (memory_info->blob != NULL)
636         memory_info->type=UnalignedVirtualMemory;
637     }
638   if (memory_info->blob == NULL)
639     memory_info=RelinquishVirtualMemory(memory_info);
640   return(memory_info);
641 }
642 \f
643 /*
644 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
645 %                                                                             %
646 %                                                                             %
647 %                                                                             %
648 %   C o p y M a g i c k M e m o r y                                           %
649 %                                                                             %
650 %                                                                             %
651 %                                                                             %
652 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
653 %
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.
657 %
658 %  The format of the CopyMagickMemory method is:
659 %
660 %      void *CopyMagickMemory(void *destination,const void *source,
661 %        const size_t size)
662 %
663 %  A description of each parameter follows:
664 %
665 %    o destination: the destination.
666 %
667 %    o source: the source.
668 %
669 %    o size: the size of the memory in bytes to allocate.
670 %
671 */
672 MagickExport void *CopyMagickMemory(void *destination,const void *source,
673   const size_t size)
674 {
675   register const unsigned char
676     *p;
677
678   register unsigned char
679     *q;
680
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)))
686     switch (size)
687     {
688       default: return(memcpy(destination,source,size));
689       case 8: *q++=(*p++);
690       case 7: *q++=(*p++);
691       case 6: *q++=(*p++);
692       case 5: *q++=(*p++);
693       case 4: *q++=(*p++);
694       case 3: *q++=(*p++);
695       case 2: *q++=(*p++);
696       case 1: *q++=(*p++);
697       case 0: return(destination);
698     }
699   return(memmove(destination,source,size));
700 }
701 \f
702 /*
703 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
704 %                                                                             %
705 %                                                                             %
706 %                                                                             %
707 +   D e s t r o y M a g i c k M e m o r y                                     %
708 %                                                                             %
709 %                                                                             %
710 %                                                                             %
711 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
712 %
713 %  DestroyMagickMemory() deallocates memory associated with the memory manager.
714 %
715 %  The format of the DestroyMagickMemory method is:
716 %
717 %      DestroyMagickMemory(void)
718 %
719 */
720 MagickExport void DestroyMagickMemory(void)
721 {
722 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
723   register ssize_t
724     i;
725
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);
734     else
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);
740 #endif
741 }
742 \f
743 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
744 /*
745 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
746 %                                                                             %
747 %                                                                             %
748 %                                                                             %
749 +   E x p a n d H e a p                                                       %
750 %                                                                             %
751 %                                                                             %
752 %                                                                             %
753 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
754 %
755 %  ExpandHeap() get more memory from the system.  It returns MagickTrue on
756 %  success otherwise MagickFalse.
757 %
758 %  The format of the ExpandHeap method is:
759 %
760 %      MagickBooleanType ExpandHeap(size_t size)
761 %
762 %  A description of each parameter follows:
763 %
764 %    o size: the size of the memory in bytes we require.
765 %
766 */
767 static MagickBooleanType ExpandHeap(size_t size)
768 {
769   DataSegmentInfo
770     *segment_info;
771
772   MagickBooleanType
773     mapped;
774
775   register ssize_t
776     i;
777
778   register void
779     *block;
780
781   size_t
782     blocksize;
783
784   void
785     *segment;
786
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)
794     return(MagickFalse);
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;
815   return(MagickTrue);
816 }
817 #endif
818 \f
819 /*
820 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
821 %                                                                             %
822 %                                                                             %
823 %                                                                             %
824 %   G e t M a g i c k M e m o r y M e t h o d s                               %
825 %                                                                             %
826 %                                                                             %
827 %                                                                             %
828 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
829 %
830 %  GetMagickMemoryMethods() gets the methods to acquire, resize, and destroy
831 %  memory.
832 %
833 %  The format of the GetMagickMemoryMethods() method is:
834 %
835 %      void GetMagickMemoryMethods(AcquireMemoryHandler *acquire_memory_handler,
836 %        ResizeMemoryHandler *resize_memory_handler,
837 %        DestroyMemoryHandler *destroy_memory_handler)
838 %
839 %  A description of each parameter follows:
840 %
841 %    o acquire_memory_handler: method to acquire memory (e.g. malloc).
842 %
843 %    o resize_memory_handler: method to resize memory (e.g. realloc).
844 %
845 %    o destroy_memory_handler: method to destroy memory (e.g. free).
846 %
847 */
848 MagickExport void GetMagickMemoryMethods(
849   AcquireMemoryHandler *acquire_memory_handler,
850   ResizeMemoryHandler *resize_memory_handler,
851   DestroyMemoryHandler *destroy_memory_handler)
852 {
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;
859 }
860 \f
861 /*
862 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
863 %                                                                             %
864 %                                                                             %
865 %                                                                             %
866 %   G e t V i r t u a l M e m o r y B l o b                                   %
867 %                                                                             %
868 %                                                                             %
869 %                                                                             %
870 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
871 %
872 %  GetVirtualMemoryBlob() returns the virtual memory blob associated with the
873 %  specified MemoryInfo structure.
874 %
875 %  The format of the GetVirtualMemoryBlob method is:
876 %
877 %      void *GetVirtualMemoryBlob(const MemoryInfo *memory_info)
878 %
879 %  A description of each parameter follows:
880 %
881 %    o memory_info: The MemoryInfo structure.
882 */
883 MagickExport void *GetVirtualMemoryBlob(const MemoryInfo *memory_info)
884 {
885   assert(memory_info != (const MemoryInfo *) NULL);
886   assert(memory_info->signature == MagickSignature);
887   return(memory_info->blob);
888 }
889 \f
890 /*
891 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
892 %                                                                             %
893 %                                                                             %
894 %                                                                             %
895 %   R e l i n q u i s h A l i g n e d M e m o r y                             %
896 %                                                                             %
897 %                                                                             %
898 %                                                                             %
899 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
900 %
901 %  RelinquishAlignedMemory() frees memory acquired with AcquireAlignedMemory()
902 %  or reuse.
903 %
904 %  The format of the RelinquishAlignedMemory method is:
905 %
906 %      void *RelinquishAlignedMemory(void *memory)
907 %
908 %  A description of each parameter follows:
909 %
910 %    o memory: A pointer to a block of memory to free for reuse.
911 %
912 */
913 MagickExport void *RelinquishAlignedMemory(void *memory)
914 {
915   if (memory == (void *) NULL)
916     return((void *) NULL);
917 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
918   free(memory);
919 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
920   _aligned_free(memory);
921 #else
922   free(*((void **) memory-1));
923 #endif
924   return(NULL);
925 }
926 \f
927 /*
928 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
929 %                                                                             %
930 %                                                                             %
931 %                                                                             %
932 %   R e l i n q u i s h M a g i c k M e m o r y                               %
933 %                                                                             %
934 %                                                                             %
935 %                                                                             %
936 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
937 %
938 %  RelinquishMagickMemory() frees memory acquired with AcquireMagickMemory()
939 %  or AcquireQuantumMemory() for reuse.
940 %
941 %  The format of the RelinquishMagickMemory method is:
942 %
943 %      void *RelinquishMagickMemory(void *memory)
944 %
945 %  A description of each parameter follows:
946 %
947 %    o memory: A pointer to a block of memory to free for reuse.
948 %
949 */
950 MagickExport void *RelinquishMagickMemory(void *memory)
951 {
952   if (memory == (void *) NULL)
953     return((void *) NULL);
954 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
955   memory_methods.destroy_memory_handler(memory);
956 #else
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)
961     {
962       void
963         *previous;
964
965       /*
966         Coalesce with previous adjacent block.
967       */
968       previous=PreviousBlock(memory);
969       RemoveFreeBlock(previous,AllocationPolicy(SizeOfBlock(previous)));
970       *BlockHeader(previous)=(SizeOfBlock(previous)+SizeOfBlock(memory)) |
971         (*BlockHeader(previous) & ~SizeMask);
972       memory=previous;
973     }
974   if ((*BlockHeader(NextBlock(NextBlock(memory))) & PreviousBlockBit) == 0)
975     {
976       void
977         *next;
978
979       /*
980         Coalesce with next adjacent block.
981       */
982       next=NextBlock(memory);
983       RemoveFreeBlock(next,AllocationPolicy(SizeOfBlock(next)));
984       *BlockHeader(memory)=(SizeOfBlock(memory)+SizeOfBlock(next)) |
985         (*BlockHeader(memory) & ~SizeMask);
986     }
987   *BlockFooter(memory,SizeOfBlock(memory))=SizeOfBlock(memory);
988   *BlockHeader(NextBlock(memory))&=(~PreviousBlockBit);
989   InsertFreeBlock(memory,AllocationPolicy(SizeOfBlock(memory)));
990   UnlockSemaphoreInfo(memory_semaphore);
991 #endif
992   return((void *) NULL);
993 }
994 \f
995 /*
996 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
997 %                                                                             %
998 %                                                                             %
999 %                                                                             %
1000 %   R e l i n q u i s h V i r t u a l M e m o r y                             %
1001 %                                                                             %
1002 %                                                                             %
1003 %                                                                             %
1004 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1005 %
1006 %  RelinquishVirtualMemory() frees memory acquired with AcquireVirtualMemory().
1007 %
1008 %  The format of the RelinquishVirtualMemory method is:
1009 %
1010 %      MemoryInfo *RelinquishVirtualMemory(MemoryInfo *memory_info)
1011 %
1012 %  A description of each parameter follows:
1013 %
1014 %    o memory_info: A pointer to a block of memory to free for reuse.
1015 %
1016 */
1017 MagickExport MemoryInfo *RelinquishVirtualMemory(MemoryInfo *memory_info)
1018 {
1019   assert(memory_info != (MemoryInfo *) NULL);
1020   assert(memory_info->signature == MagickSignature);
1021   if (memory_info->blob != (void *) NULL)
1022     switch (memory_info->type)
1023     {
1024       case AlignedVirtualMemory:
1025       {
1026         memory_info->blob=RelinquishAlignedMemory(memory_info->blob);
1027         RelinquishMagickResource(MemoryResource,memory_info->length);
1028         break;
1029       }
1030       case MapVirtualMemory:
1031       {
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);
1037         break;
1038       }
1039       case UnalignedVirtualMemory:
1040       default:
1041       {
1042         memory_info->blob=RelinquishMagickMemory(memory_info->blob);
1043         break;
1044       }
1045     }
1046   memory_info->signature=(~MagickSignature);
1047   memory_info=(MemoryInfo *) RelinquishAlignedMemory(memory_info);
1048   return(memory_info);
1049 }
1050 \f
1051 /*
1052 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1053 %                                                                             %
1054 %                                                                             %
1055 %                                                                             %
1056 %   R e s e t M a g i c k M e m o r y                                         %
1057 %                                                                             %
1058 %                                                                             %
1059 %                                                                             %
1060 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1061 %
1062 %  ResetMagickMemory() fills the first size bytes of the memory area pointed to
1063 %  by memory with the constant byte c.
1064 %
1065 %  The format of the ResetMagickMemory method is:
1066 %
1067 %      void *ResetMagickMemory(void *memory,int byte,const size_t size)
1068 %
1069 %  A description of each parameter follows:
1070 %
1071 %    o memory: a pointer to a memory allocation.
1072 %
1073 %    o byte: set the memory to this value.
1074 %
1075 %    o size: size of the memory to reset.
1076 %
1077 */
1078 MagickExport void *ResetMagickMemory(void *memory,int byte,const size_t size)
1079 {
1080   assert(memory != (void *) NULL);
1081   return(memset(memory,byte,size));
1082 }
1083 \f
1084 /*
1085 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1086 %                                                                             %
1087 %                                                                             %
1088 %                                                                             %
1089 %   R e s i z e M a g i c k M e m o r y                                       %
1090 %                                                                             %
1091 %                                                                             %
1092 %                                                                             %
1093 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1094 %
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.
1098 %
1099 %  The format of the ResizeMagickMemory method is:
1100 %
1101 %      void *ResizeMagickMemory(void *memory,const size_t size)
1102 %
1103 %  A description of each parameter follows:
1104 %
1105 %    o memory: A pointer to a memory allocation.
1106 %
1107 %    o size: the new size of the allocated memory.
1108 %
1109 */
1110
1111 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
1112 static inline void *ResizeBlock(void *block,size_t size)
1113 {
1114   register void
1115     *memory;
1116
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);
1124   else
1125     (void) memcpy(memory,block,SizeOfBlock(block)-sizeof(size_t));
1126   memory_pool.allocation+=size;
1127   return(memory);
1128 }
1129 #endif
1130
1131 MagickExport void *ResizeMagickMemory(void *memory,const size_t size)
1132 {
1133   register void
1134     *block;
1135
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);
1142 #else
1143   LockSemaphoreInfo(memory_semaphore);
1144   block=ResizeBlock(memory,size == 0 ? 1UL : size);
1145   if (block == (void *) NULL)
1146     {
1147       if (ExpandHeap(size == 0 ? 1UL : size) == MagickFalse)
1148         {
1149           UnlockSemaphoreInfo(memory_semaphore);
1150           memory=RelinquishMagickMemory(memory);
1151           ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1152         }
1153       block=ResizeBlock(memory,size == 0 ? 1UL : size);
1154       assert(block != (void *) NULL);
1155     }
1156   UnlockSemaphoreInfo(memory_semaphore);
1157   memory=RelinquishMagickMemory(memory);
1158 #endif
1159   return(block);
1160 }
1161 \f
1162 /*
1163 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1164 %                                                                             %
1165 %                                                                             %
1166 %                                                                             %
1167 %   R e s i z e Q u a n t u m M e m o r y                                     %
1168 %                                                                             %
1169 %                                                                             %
1170 %                                                                             %
1171 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1172 %
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.
1176 %
1177 %  The format of the ResizeQuantumMemory method is:
1178 %
1179 %      void *ResizeQuantumMemory(void *memory,const size_t count,
1180 %        const size_t quantum)
1181 %
1182 %  A description of each parameter follows:
1183 %
1184 %    o memory: A pointer to a memory allocation.
1185 %
1186 %    o count: the number of quantum elements to allocate.
1187 %
1188 %    o quantum: the number of bytes in each quantum.
1189 %
1190 */
1191 MagickExport void *ResizeQuantumMemory(void *memory,const size_t count,
1192   const size_t quantum)
1193 {
1194   size_t
1195     size;
1196
1197   size=count*quantum;
1198   if ((count == 0) || (quantum != (size/count)))
1199     {
1200       memory=RelinquishMagickMemory(memory);
1201       errno=ENOMEM;
1202       return((void *) NULL);
1203     }
1204   return(ResizeMagickMemory(memory,size));
1205 }
1206 \f
1207 /*
1208 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1209 %                                                                             %
1210 %                                                                             %
1211 %                                                                             %
1212 %   S e t M a g i c k M e m o r y M e t h o d s                               %
1213 %                                                                             %
1214 %                                                                             %
1215 %                                                                             %
1216 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1217 %
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.
1221 %
1222 %  The format of the SetMagickMemoryMethods() method is:
1223 %
1224 %      SetMagickMemoryMethods(AcquireMemoryHandler acquire_memory_handler,
1225 %        ResizeMemoryHandler resize_memory_handler,
1226 %        DestroyMemoryHandler destroy_memory_handler)
1227 %
1228 %  A description of each parameter follows:
1229 %
1230 %    o acquire_memory_handler: method to acquire memory (e.g. malloc).
1231 %
1232 %    o resize_memory_handler: method to resize memory (e.g. realloc).
1233 %
1234 %    o destroy_memory_handler: method to destroy memory (e.g. free).
1235 %
1236 */
1237 MagickExport void SetMagickMemoryMethods(
1238   AcquireMemoryHandler acquire_memory_handler,
1239   ResizeMemoryHandler resize_memory_handler,
1240   DestroyMemoryHandler destroy_memory_handler)
1241 {
1242   /*
1243     Set memory methods.
1244   */
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;
1251 }