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