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