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