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