memory.c revision e1c94d9d25db6b0dd7a5028ffee31d1057855d73
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-2015 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[MagickPathExtent];
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    ActivateSemaphoreInfo(&memory_semaphore);
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=MagickCoreSignature;
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      (AcquireMagickResource(DiskResource,length) != MagickFalse))
611    {
612      int
613        file;
614
615      /*
616        Anonymous memory mapping failed, try file-backed memory mapping.
617      */
618      file=AcquireUniqueFileResource(memory_info->filename);
619      if (file == -1)
620        RelinquishMagickResource(DiskResource,length);
621      else
622        {
623          if ((lseek(file,length-1,SEEK_SET) < 0) || (write(file,"",1) != 1))
624            RelinquishMagickResource(DiskResource,length);
625          else
626            {
627              if (AcquireMagickResource(MapResource,length) == MagickFalse)
628                RelinquishMagickResource(DiskResource,length);
629              else
630                {
631                  memory_info->blob=MapBlob(file,IOMode,0,length);
632                  if (memory_info->blob != NULL)
633                    memory_info->type=MapVirtualMemory;
634                  else
635                    {
636                      RelinquishMagickResource(MapResource,length);
637                      RelinquishMagickResource(DiskResource,length);
638                    }
639                }
640            }
641          (void) close(file);
642        }
643    }
644  if (memory_info->blob == NULL)
645    {
646      memory_info->blob=AcquireMagickMemory(length);
647      if (memory_info->blob != NULL)
648        memory_info->type=UnalignedVirtualMemory;
649    }
650  if (memory_info->blob == NULL)
651    memory_info=RelinquishVirtualMemory(memory_info);
652  return(memory_info);
653}
654
655/*
656%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
657%                                                                             %
658%                                                                             %
659%                                                                             %
660%   C o p y M a g i c k M e m o r y                                           %
661%                                                                             %
662%                                                                             %
663%                                                                             %
664%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
665%
666%  CopyMagickMemory() copies size bytes from memory area source to the
667%  destination.  Copying between objects that overlap will take place
668%  correctly.  It returns destination.
669%
670%  The format of the CopyMagickMemory method is:
671%
672%      void *CopyMagickMemory(void *destination,const void *source,
673%        const size_t size)
674%
675%  A description of each parameter follows:
676%
677%    o destination: the destination.
678%
679%    o source: the source.
680%
681%    o size: the size of the memory in bytes to allocate.
682%
683*/
684MagickExport void *CopyMagickMemory(void *destination,const void *source,
685  const size_t size)
686{
687  register const unsigned char
688    *p;
689
690  register unsigned char
691    *q;
692
693  assert(destination != (void *) NULL);
694  assert(source != (const void *) NULL);
695  p=(const unsigned char *) source;
696  q=(unsigned char *) destination;
697  if (((q+size) < p) || (q > (p+size)))
698    switch (size)
699    {
700      default: return(memcpy(destination,source,size));
701      case 8: *q++=(*p++);
702      case 7: *q++=(*p++);
703      case 6: *q++=(*p++);
704      case 5: *q++=(*p++);
705      case 4: *q++=(*p++);
706      case 3: *q++=(*p++);
707      case 2: *q++=(*p++);
708      case 1: *q++=(*p++);
709      case 0: return(destination);
710    }
711  return(memmove(destination,source,size));
712}
713
714/*
715%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
716%                                                                             %
717%                                                                             %
718%                                                                             %
719+   D e s t r o y M a g i c k M e m o r y                                     %
720%                                                                             %
721%                                                                             %
722%                                                                             %
723%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
724%
725%  DestroyMagickMemory() deallocates memory associated with the memory manager.
726%
727%  The format of the DestroyMagickMemory method is:
728%
729%      DestroyMagickMemory(void)
730%
731*/
732MagickExport void DestroyMagickMemory(void)
733{
734#if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
735  register ssize_t
736    i;
737
738  if (memory_semaphore == (SemaphoreInfo *) NULL)
739    ActivateSemaphoreInfo(&memory_semaphore);
740  LockSemaphoreInfo(memory_semaphore);
741  for (i=0; i < (ssize_t) memory_pool.number_segments; i++)
742    if (memory_pool.segments[i]->mapped == MagickFalse)
743      memory_methods.destroy_memory_handler(
744        memory_pool.segments[i]->allocation);
745    else
746      (void) UnmapBlob(memory_pool.segments[i]->allocation,
747        memory_pool.segments[i]->length);
748  free_segments=(DataSegmentInfo *) NULL;
749  (void) ResetMagickMemory(&memory_pool,0,sizeof(memory_pool));
750  UnlockSemaphoreInfo(memory_semaphore);
751  RelinquishSemaphoreInfo(&memory_semaphore);
752#endif
753}
754
755#if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
756/*
757%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
758%                                                                             %
759%                                                                             %
760%                                                                             %
761+   E x p a n d H e a p                                                       %
762%                                                                             %
763%                                                                             %
764%                                                                             %
765%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
766%
767%  ExpandHeap() get more memory from the system.  It returns MagickTrue on
768%  success otherwise MagickFalse.
769%
770%  The format of the ExpandHeap method is:
771%
772%      MagickBooleanType ExpandHeap(size_t size)
773%
774%  A description of each parameter follows:
775%
776%    o size: the size of the memory in bytes we require.
777%
778*/
779static MagickBooleanType ExpandHeap(size_t size)
780{
781  DataSegmentInfo
782    *segment_info;
783
784  MagickBooleanType
785    mapped;
786
787  register ssize_t
788    i;
789
790  register void
791    *block;
792
793  size_t
794    blocksize;
795
796  void
797    *segment;
798
799  blocksize=((size+12*sizeof(size_t))+SegmentSize-1) & -SegmentSize;
800  assert(memory_pool.number_segments < MaxSegments);
801  segment=MapBlob(-1,IOMode,0,blocksize);
802  mapped=segment != (void *) NULL ? MagickTrue : MagickFalse;
803  if (segment == (void *) NULL)
804    segment=(void *) memory_methods.acquire_memory_handler(blocksize);
805  if (segment == (void *) NULL)
806    return(MagickFalse);
807  segment_info=(DataSegmentInfo *) free_segments;
808  free_segments=segment_info->next;
809  segment_info->mapped=mapped;
810  segment_info->length=blocksize;
811  segment_info->allocation=segment;
812  segment_info->bound=(char *) segment+blocksize;
813  i=(ssize_t) memory_pool.number_segments-1;
814  for ( ; (i >= 0) && (memory_pool.segments[i]->allocation > segment); i--)
815    memory_pool.segments[i+1]=memory_pool.segments[i];
816  memory_pool.segments[i+1]=segment_info;
817  memory_pool.number_segments++;
818  size=blocksize-12*sizeof(size_t);
819  block=(char *) segment_info->allocation+4*sizeof(size_t);
820  *BlockHeader(block)=size | PreviousBlockBit;
821  *BlockFooter(block,size)=size;
822  InsertFreeBlock(block,AllocationPolicy(size));
823  block=NextBlock(block);
824  assert(block < segment_info->bound);
825  *BlockHeader(block)=2*sizeof(size_t);
826  *BlockHeader(NextBlock(block))=PreviousBlockBit;
827  return(MagickTrue);
828}
829#endif
830
831/*
832%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
833%                                                                             %
834%                                                                             %
835%                                                                             %
836%   G e t M a g i c k M e m o r y M e t h o d s                               %
837%                                                                             %
838%                                                                             %
839%                                                                             %
840%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
841%
842%  GetMagickMemoryMethods() gets the methods to acquire, resize, and destroy
843%  memory.
844%
845%  The format of the GetMagickMemoryMethods() method is:
846%
847%      void GetMagickMemoryMethods(AcquireMemoryHandler *acquire_memory_handler,
848%        ResizeMemoryHandler *resize_memory_handler,
849%        DestroyMemoryHandler *destroy_memory_handler)
850%
851%  A description of each parameter follows:
852%
853%    o acquire_memory_handler: method to acquire memory (e.g. malloc).
854%
855%    o resize_memory_handler: method to resize memory (e.g. realloc).
856%
857%    o destroy_memory_handler: method to destroy memory (e.g. free).
858%
859*/
860MagickExport void GetMagickMemoryMethods(
861  AcquireMemoryHandler *acquire_memory_handler,
862  ResizeMemoryHandler *resize_memory_handler,
863  DestroyMemoryHandler *destroy_memory_handler)
864{
865  assert(acquire_memory_handler != (AcquireMemoryHandler *) NULL);
866  assert(resize_memory_handler != (ResizeMemoryHandler *) NULL);
867  assert(destroy_memory_handler != (DestroyMemoryHandler *) NULL);
868  *acquire_memory_handler=memory_methods.acquire_memory_handler;
869  *resize_memory_handler=memory_methods.resize_memory_handler;
870  *destroy_memory_handler=memory_methods.destroy_memory_handler;
871}
872
873/*
874%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
875%                                                                             %
876%                                                                             %
877%                                                                             %
878%   G e t V i r t u a l M e m o r y B l o b                                   %
879%                                                                             %
880%                                                                             %
881%                                                                             %
882%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
883%
884%  GetVirtualMemoryBlob() returns the virtual memory blob associated with the
885%  specified MemoryInfo structure.
886%
887%  The format of the GetVirtualMemoryBlob method is:
888%
889%      void *GetVirtualMemoryBlob(const MemoryInfo *memory_info)
890%
891%  A description of each parameter follows:
892%
893%    o memory_info: The MemoryInfo structure.
894*/
895MagickExport void *GetVirtualMemoryBlob(const MemoryInfo *memory_info)
896{
897  assert(memory_info != (const MemoryInfo *) NULL);
898  assert(memory_info->signature == MagickCoreSignature);
899  return(memory_info->blob);
900}
901
902/*
903%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
904%                                                                             %
905%                                                                             %
906%                                                                             %
907%   R e l i n q u i s h A l i g n e d M e m o r y                             %
908%                                                                             %
909%                                                                             %
910%                                                                             %
911%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
912%
913%  RelinquishAlignedMemory() frees memory acquired with AcquireAlignedMemory()
914%  or reuse.
915%
916%  The format of the RelinquishAlignedMemory method is:
917%
918%      void *RelinquishAlignedMemory(void *memory)
919%
920%  A description of each parameter follows:
921%
922%    o memory: A pointer to a block of memory to free for reuse.
923%
924*/
925MagickExport void *RelinquishAlignedMemory(void *memory)
926{
927  if (memory == (void *) NULL)
928    return((void *) NULL);
929#if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
930  free(memory);
931#elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
932  _aligned_free(memory);
933#else
934  free(*((void **) memory-1));
935#endif
936  return(NULL);
937}
938
939/*
940%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
941%                                                                             %
942%                                                                             %
943%                                                                             %
944%   R e l i n q u i s h M a g i c k M e m o r y                               %
945%                                                                             %
946%                                                                             %
947%                                                                             %
948%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
949%
950%  RelinquishMagickMemory() frees memory acquired with AcquireMagickMemory()
951%  or AcquireQuantumMemory() for reuse.
952%
953%  The format of the RelinquishMagickMemory method is:
954%
955%      void *RelinquishMagickMemory(void *memory)
956%
957%  A description of each parameter follows:
958%
959%    o memory: A pointer to a block of memory to free for reuse.
960%
961*/
962MagickExport void *RelinquishMagickMemory(void *memory)
963{
964  if (memory == (void *) NULL)
965    return((void *) NULL);
966#if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
967  memory_methods.destroy_memory_handler(memory);
968#else
969  LockSemaphoreInfo(memory_semaphore);
970  assert((SizeOfBlock(memory) % (4*sizeof(size_t))) == 0);
971  assert((*BlockHeader(NextBlock(memory)) & PreviousBlockBit) != 0);
972  if ((*BlockHeader(memory) & PreviousBlockBit) == 0)
973    {
974      void
975        *previous;
976
977      /*
978        Coalesce with previous adjacent block.
979      */
980      previous=PreviousBlock(memory);
981      RemoveFreeBlock(previous,AllocationPolicy(SizeOfBlock(previous)));
982      *BlockHeader(previous)=(SizeOfBlock(previous)+SizeOfBlock(memory)) |
983        (*BlockHeader(previous) & ~SizeMask);
984      memory=previous;
985    }
986  if ((*BlockHeader(NextBlock(NextBlock(memory))) & PreviousBlockBit) == 0)
987    {
988      void
989        *next;
990
991      /*
992        Coalesce with next adjacent block.
993      */
994      next=NextBlock(memory);
995      RemoveFreeBlock(next,AllocationPolicy(SizeOfBlock(next)));
996      *BlockHeader(memory)=(SizeOfBlock(memory)+SizeOfBlock(next)) |
997        (*BlockHeader(memory) & ~SizeMask);
998    }
999  *BlockFooter(memory,SizeOfBlock(memory))=SizeOfBlock(memory);
1000  *BlockHeader(NextBlock(memory))&=(~PreviousBlockBit);
1001  InsertFreeBlock(memory,AllocationPolicy(SizeOfBlock(memory)));
1002  UnlockSemaphoreInfo(memory_semaphore);
1003#endif
1004  return((void *) NULL);
1005}
1006
1007/*
1008%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1009%                                                                             %
1010%                                                                             %
1011%                                                                             %
1012%   R e l i n q u i s h V i r t u a l M e m o r y                             %
1013%                                                                             %
1014%                                                                             %
1015%                                                                             %
1016%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1017%
1018%  RelinquishVirtualMemory() frees memory acquired with AcquireVirtualMemory().
1019%
1020%  The format of the RelinquishVirtualMemory method is:
1021%
1022%      MemoryInfo *RelinquishVirtualMemory(MemoryInfo *memory_info)
1023%
1024%  A description of each parameter follows:
1025%
1026%    o memory_info: A pointer to a block of memory to free for reuse.
1027%
1028*/
1029MagickExport MemoryInfo *RelinquishVirtualMemory(MemoryInfo *memory_info)
1030{
1031  assert(memory_info != (MemoryInfo *) NULL);
1032  assert(memory_info->signature == MagickCoreSignature);
1033  if (memory_info->blob != (void *) NULL)
1034    switch (memory_info->type)
1035    {
1036      case AlignedVirtualMemory:
1037      {
1038        memory_info->blob=RelinquishAlignedMemory(memory_info->blob);
1039        RelinquishMagickResource(MemoryResource,memory_info->length);
1040        break;
1041      }
1042      case MapVirtualMemory:
1043      {
1044        (void) UnmapBlob(memory_info->blob,memory_info->length);
1045        memory_info->blob=NULL;
1046        RelinquishMagickResource(MapResource,memory_info->length);
1047        if (*memory_info->filename != '\0')
1048          {
1049            (void) RelinquishUniqueFileResource(memory_info->filename);
1050            RelinquishMagickResource(DiskResource,memory_info->length);
1051          }
1052        break;
1053      }
1054      case UnalignedVirtualMemory:
1055      default:
1056      {
1057        memory_info->blob=RelinquishMagickMemory(memory_info->blob);
1058        break;
1059      }
1060    }
1061  memory_info->signature=(~MagickCoreSignature);
1062  memory_info=(MemoryInfo *) RelinquishAlignedMemory(memory_info);
1063  return(memory_info);
1064}
1065
1066/*
1067%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1068%                                                                             %
1069%                                                                             %
1070%                                                                             %
1071%   R e s e t M a g i c k M e m o r y                                         %
1072%                                                                             %
1073%                                                                             %
1074%                                                                             %
1075%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1076%
1077%  ResetMagickMemory() fills the first size bytes of the memory area pointed to
1078%  by memory with the constant byte c.
1079%
1080%  The format of the ResetMagickMemory method is:
1081%
1082%      void *ResetMagickMemory(void *memory,int byte,const size_t size)
1083%
1084%  A description of each parameter follows:
1085%
1086%    o memory: a pointer to a memory allocation.
1087%
1088%    o byte: set the memory to this value.
1089%
1090%    o size: size of the memory to reset.
1091%
1092*/
1093MagickExport void *ResetMagickMemory(void *memory,int byte,const size_t size)
1094{
1095  assert(memory != (void *) NULL);
1096  return(memset(memory,byte,size));
1097}
1098
1099/*
1100%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1101%                                                                             %
1102%                                                                             %
1103%                                                                             %
1104%   R e s i z e M a g i c k M e m o r y                                       %
1105%                                                                             %
1106%                                                                             %
1107%                                                                             %
1108%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1109%
1110%  ResizeMagickMemory() changes the size of the memory and returns a pointer to
1111%  the (possibly moved) block.  The contents will be unchanged up to the
1112%  lesser of the new and old sizes.
1113%
1114%  The format of the ResizeMagickMemory method is:
1115%
1116%      void *ResizeMagickMemory(void *memory,const size_t size)
1117%
1118%  A description of each parameter follows:
1119%
1120%    o memory: A pointer to a memory allocation.
1121%
1122%    o size: the new size of the allocated memory.
1123%
1124*/
1125
1126#if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
1127static inline void *ResizeBlock(void *block,size_t size)
1128{
1129  register void
1130    *memory;
1131
1132  if (block == (void *) NULL)
1133    return(AcquireBlock(size));
1134  memory=AcquireBlock(size);
1135  if (memory == (void *) NULL)
1136    return((void *) NULL);
1137  if (size <= (SizeOfBlock(block)-sizeof(size_t)))
1138    (void) memcpy(memory,block,size);
1139  else
1140    (void) memcpy(memory,block,SizeOfBlock(block)-sizeof(size_t));
1141  memory_pool.allocation+=size;
1142  return(memory);
1143}
1144#endif
1145
1146MagickExport void *ResizeMagickMemory(void *memory,const size_t size)
1147{
1148  register void
1149    *block;
1150
1151  if (memory == (void *) NULL)
1152    return(AcquireMagickMemory(size));
1153#if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
1154  block=memory_methods.resize_memory_handler(memory,size == 0 ? 1UL : size);
1155  if (block == (void *) NULL)
1156    memory=RelinquishMagickMemory(memory);
1157#else
1158  LockSemaphoreInfo(memory_semaphore);
1159  block=ResizeBlock(memory,size == 0 ? 1UL : size);
1160  if (block == (void *) NULL)
1161    {
1162      if (ExpandHeap(size == 0 ? 1UL : size) == MagickFalse)
1163        {
1164          UnlockSemaphoreInfo(memory_semaphore);
1165          memory=RelinquishMagickMemory(memory);
1166          ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1167        }
1168      block=ResizeBlock(memory,size == 0 ? 1UL : size);
1169      assert(block != (void *) NULL);
1170    }
1171  UnlockSemaphoreInfo(memory_semaphore);
1172  memory=RelinquishMagickMemory(memory);
1173#endif
1174  return(block);
1175}
1176
1177/*
1178%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1179%                                                                             %
1180%                                                                             %
1181%                                                                             %
1182%   R e s i z e Q u a n t u m M e m o r y                                     %
1183%                                                                             %
1184%                                                                             %
1185%                                                                             %
1186%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1187%
1188%  ResizeQuantumMemory() changes the size of the memory and returns a pointer
1189%  to the (possibly moved) block.  The contents will be unchanged up to the
1190%  lesser of the new and old sizes.
1191%
1192%  The format of the ResizeQuantumMemory method is:
1193%
1194%      void *ResizeQuantumMemory(void *memory,const size_t count,
1195%        const size_t quantum)
1196%
1197%  A description of each parameter follows:
1198%
1199%    o memory: A pointer to a memory allocation.
1200%
1201%    o count: the number of quantum elements to allocate.
1202%
1203%    o quantum: the number of bytes in each quantum.
1204%
1205*/
1206MagickExport void *ResizeQuantumMemory(void *memory,const size_t count,
1207  const size_t quantum)
1208{
1209  size_t
1210    size;
1211
1212  size=count*quantum;
1213  if ((count == 0) || (quantum != (size/count)))
1214    {
1215      memory=RelinquishMagickMemory(memory);
1216      errno=ENOMEM;
1217      return((void *) NULL);
1218    }
1219  return(ResizeMagickMemory(memory,size));
1220}
1221
1222/*
1223%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1224%                                                                             %
1225%                                                                             %
1226%                                                                             %
1227%   S e t M a g i c k M e m o r y M e t h o d s                               %
1228%                                                                             %
1229%                                                                             %
1230%                                                                             %
1231%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1232%
1233%  SetMagickMemoryMethods() sets the methods to acquire, resize, and destroy
1234%  memory. Your custom memory methods must be set prior to the
1235%  MagickCoreGenesis() method.
1236%
1237%  The format of the SetMagickMemoryMethods() method is:
1238%
1239%      SetMagickMemoryMethods(AcquireMemoryHandler acquire_memory_handler,
1240%        ResizeMemoryHandler resize_memory_handler,
1241%        DestroyMemoryHandler destroy_memory_handler)
1242%
1243%  A description of each parameter follows:
1244%
1245%    o acquire_memory_handler: method to acquire memory (e.g. malloc).
1246%
1247%    o resize_memory_handler: method to resize memory (e.g. realloc).
1248%
1249%    o destroy_memory_handler: method to destroy memory (e.g. free).
1250%
1251*/
1252MagickExport void SetMagickMemoryMethods(
1253  AcquireMemoryHandler acquire_memory_handler,
1254  ResizeMemoryHandler resize_memory_handler,
1255  DestroyMemoryHandler destroy_memory_handler)
1256{
1257  /*
1258    Set memory methods.
1259  */
1260  if (acquire_memory_handler != (AcquireMemoryHandler) NULL)
1261    memory_methods.acquire_memory_handler=acquire_memory_handler;
1262  if (resize_memory_handler != (ResizeMemoryHandler) NULL)
1263    memory_methods.resize_memory_handler=resize_memory_handler;
1264  if (destroy_memory_handler != (DestroyMemoryHandler) NULL)
1265    memory_methods.destroy_memory_handler=destroy_memory_handler;
1266}
1267