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