memory.c revision 636a20e106d2e32a12ae55edf5d47e988e0d5d38
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/semaphore.h"
64#include "MagickCore/string_.h"
65
66/*
67  Define declarations.
68*/
69#define BlockFooter(block,size) \
70  ((size_t *) ((char *) (block)+(size)-2*sizeof(size_t)))
71#define BlockHeader(block)  ((size_t *) (block)-1)
72#define BlockSize  4096
73#define BlockThreshold  1024
74#define MaxBlockExponent  16
75#define MaxBlocks ((BlockThreshold/(4*sizeof(size_t)))+MaxBlockExponent+1)
76#define MaxSegments  1024
77#define MemoryGuard  ((0xdeadbeef << 31)+0xdeafdeed)
78#define NextBlock(block)  ((char *) (block)+SizeOfBlock(block))
79#define NextBlockInList(block)  (*(void **) (block))
80#define PreviousBlock(block)  ((char *) (block)-(*((size_t *) (block)-2)))
81#define PreviousBlockBit  0x01
82#define PreviousBlockInList(block)  (*((void **) (block)+1))
83#define SegmentSize  (2*1024*1024)
84#define SizeMask  (~0x01)
85#define SizeOfBlock(block)  (*BlockHeader(block) & SizeMask)
86
87/*
88  Typedef declarations.
89*/
90typedef struct _DataSegmentInfo
91{
92  void
93    *allocation,
94    *bound;
95
96  MagickBooleanType
97    mapped;
98
99  size_t
100    length;
101
102  struct _DataSegmentInfo
103    *previous,
104    *next;
105} DataSegmentInfo;
106
107typedef struct _MemoryInfo
108{
109  size_t
110    allocation;
111
112  void
113    *blocks[MaxBlocks+1];
114
115  size_t
116    number_segments;
117
118  DataSegmentInfo
119    *segments[MaxSegments],
120    segment_pool[MaxSegments];
121} MemoryInfo;
122
123typedef struct _MagickMemoryMethods
124{
125  AcquireMemoryHandler
126    acquire_memory_handler;
127
128  ResizeMemoryHandler
129    resize_memory_handler;
130
131  DestroyMemoryHandler
132    destroy_memory_handler;
133} MagickMemoryMethods;
134
135
136/*
137  Global declarations.
138*/
139static MagickMemoryMethods
140  memory_methods =
141  {
142    (AcquireMemoryHandler) malloc,
143    (ResizeMemoryHandler) realloc,
144    (DestroyMemoryHandler) free
145  };
146
147#if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
148static MemoryInfo
149  memory_info;
150
151static SemaphoreInfo
152  *memory_semaphore = (SemaphoreInfo *) NULL;
153
154static volatile DataSegmentInfo
155  *free_segments = (DataSegmentInfo *) NULL;
156
157/*
158  Forward declarations.
159*/
160static MagickBooleanType
161  ExpandHeap(size_t);
162#endif
163
164/*
165%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
166%                                                                             %
167%                                                                             %
168%                                                                             %
169%   A c q u i r e A l i g n e d M e m o r y                                   %
170%                                                                             %
171%                                                                             %
172%                                                                             %
173%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
174%
175%  AcquireAlignedMemory() returns a pointer to a block of memory at least size
176%  bytes whose address is a multiple of 16*sizeof(void *).
177%
178%  The format of the AcquireAlignedMemory method is:
179%
180%      void *AcquireAlignedMemory(const size_t count,const size_t quantum)
181%
182%  A description of each parameter follows:
183%
184%    o count: the number of quantum elements to allocate.
185%
186%    o quantum: the number of bytes in each quantum.
187%
188*/
189MagickExport void *AcquireAlignedMemory(const size_t count,const size_t quantum)
190{
191#define AlignedExtent(size,alignment) \
192  (((size)+((alignment)-1)) & ~((alignment)-1))
193
194  size_t
195    alignment,
196    extent,
197    size;
198
199  void
200    *memory;
201
202  size=count*quantum;
203  if ((count == 0) || (quantum != (size/count)))
204    {
205      errno=ENOMEM;
206      return((void *) NULL);
207    }
208  memory=NULL;
209  alignment=CACHE_LINE_SIZE;
210  extent=AlignedExtent(size,alignment);
211  if ((size == 0) || (alignment < sizeof(void *)) || (extent < size))
212    return((void *) NULL);
213#if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
214  if (posix_memalign(&memory,alignment,extent) != 0)
215    memory=NULL;
216#elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
217  memory=_aligned_malloc(extent,alignment);
218#else
219  {
220    void
221      *p;
222
223    extent=(size+alignment-1)+sizeof(void *);
224    if (extent > size)
225      {
226        p=malloc(extent);
227        if (p != NULL)
228          {
229            memory=(void *) AlignedExtent((size_t) p+sizeof(void *),alignment);
230            *((void **) memory-1)=p;
231          }
232      }
233  }
234#endif
235  return(memory);
236}
237
238#if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
239/*
240%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
241%                                                                             %
242%                                                                             %
243%                                                                             %
244+   A c q u i r e B l o c k                                                   %
245%                                                                             %
246%                                                                             %
247%                                                                             %
248%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
249%
250%  AcquireBlock() returns a pointer to a block of memory at least size bytes
251%  suitably aligned for any use.
252%
253%  The format of the AcquireBlock method is:
254%
255%      void *AcquireBlock(const size_t size)
256%
257%  A description of each parameter follows:
258%
259%    o size: the size of the memory in bytes to allocate.
260%
261*/
262
263static inline size_t AllocationPolicy(size_t size)
264{
265  register size_t
266    blocksize;
267
268  /*
269    The linear distribution.
270  */
271  assert(size != 0);
272  assert(size % (4*sizeof(size_t)) == 0);
273  if (size <= BlockThreshold)
274    return(size/(4*sizeof(size_t)));
275  /*
276    Check for the largest block size.
277  */
278  if (size > (size_t) (BlockThreshold*(1L << (MaxBlockExponent-1L))))
279    return(MaxBlocks-1L);
280  /*
281    Otherwise use a power of two distribution.
282  */
283  blocksize=BlockThreshold/(4*sizeof(size_t));
284  for ( ; size > BlockThreshold; size/=2)
285    blocksize++;
286  assert(blocksize > (BlockThreshold/(4*sizeof(size_t))));
287  assert(blocksize < (MaxBlocks-1L));
288  return(blocksize);
289}
290
291static inline void InsertFreeBlock(void *block,const size_t i)
292{
293  register void
294    *next,
295    *previous;
296
297  size_t
298    size;
299
300  size=SizeOfBlock(block);
301  previous=(void *) NULL;
302  next=memory_info.blocks[i];
303  while ((next != (void *) NULL) && (SizeOfBlock(next) < size))
304  {
305    previous=next;
306    next=NextBlockInList(next);
307  }
308  PreviousBlockInList(block)=previous;
309  NextBlockInList(block)=next;
310  if (previous != (void *) NULL)
311    NextBlockInList(previous)=block;
312  else
313    memory_info.blocks[i]=block;
314  if (next != (void *) NULL)
315    PreviousBlockInList(next)=block;
316}
317
318static inline void RemoveFreeBlock(void *block,const size_t i)
319{
320  register void
321    *next,
322    *previous;
323
324  next=NextBlockInList(block);
325  previous=PreviousBlockInList(block);
326  if (previous == (void *) NULL)
327    memory_info.blocks[i]=next;
328  else
329    NextBlockInList(previous)=next;
330  if (next != (void *) NULL)
331    PreviousBlockInList(next)=previous;
332}
333
334static void *AcquireBlock(size_t size)
335{
336  register size_t
337    i;
338
339  register void
340    *block;
341
342  /*
343    Find free block.
344  */
345  size=(size_t) (size+sizeof(size_t)+6*sizeof(size_t)-1) & -(4U*sizeof(size_t));
346  i=AllocationPolicy(size);
347  block=memory_info.blocks[i];
348  while ((block != (void *) NULL) && (SizeOfBlock(block) < size))
349    block=NextBlockInList(block);
350  if (block == (void *) NULL)
351    {
352      i++;
353      while (memory_info.blocks[i] == (void *) NULL)
354        i++;
355      block=memory_info.blocks[i];
356      if (i >= MaxBlocks)
357        return((void *) NULL);
358    }
359  assert((*BlockHeader(NextBlock(block)) & PreviousBlockBit) == 0);
360  assert(SizeOfBlock(block) >= size);
361  RemoveFreeBlock(block,AllocationPolicy(SizeOfBlock(block)));
362  if (SizeOfBlock(block) > size)
363    {
364      size_t
365        blocksize;
366
367      void
368        *next;
369
370      /*
371        Split block.
372      */
373      next=(char *) block+size;
374      blocksize=SizeOfBlock(block)-size;
375      *BlockHeader(next)=blocksize;
376      *BlockFooter(next,blocksize)=blocksize;
377      InsertFreeBlock(next,AllocationPolicy(blocksize));
378      *BlockHeader(block)=size | (*BlockHeader(block) & ~SizeMask);
379    }
380  assert(size == SizeOfBlock(block));
381  *BlockHeader(NextBlock(block))|=PreviousBlockBit;
382  memory_info.allocation+=size;
383  return(block);
384}
385#endif
386
387/*
388%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
389%                                                                             %
390%                                                                             %
391%                                                                             %
392%   A c q u i r e M a g i c k M e m o r y                                     %
393%                                                                             %
394%                                                                             %
395%                                                                             %
396%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
397%
398%  AcquireMagickMemory() returns a pointer to a block of memory at least size
399%  bytes suitably aligned for any use.
400%
401%  The format of the AcquireMagickMemory method is:
402%
403%      void *AcquireMagickMemory(const size_t size)
404%
405%  A description of each parameter follows:
406%
407%    o size: the size of the memory in bytes to allocate.
408%
409*/
410MagickExport void *AcquireMagickMemory(const size_t size)
411{
412  register void
413    *memory;
414
415#if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
416  memory=memory_methods.acquire_memory_handler(size == 0 ? 1UL : size);
417#else
418  if (memory_semaphore == (SemaphoreInfo *) NULL)
419    AcquireSemaphoreInfo(&memory_semaphore);
420  if (free_segments == (DataSegmentInfo *) NULL)
421    {
422      LockSemaphoreInfo(memory_semaphore);
423      if (free_segments == (DataSegmentInfo *) NULL)
424        {
425          register ssize_t
426            i;
427
428          assert(2*sizeof(size_t) > (size_t) (~SizeMask));
429          (void) ResetMagickMemory(&memory_info,0,sizeof(memory_info));
430          memory_info.allocation=SegmentSize;
431          memory_info.blocks[MaxBlocks]=(void *) (-1);
432          for (i=0; i < MaxSegments; i++)
433          {
434            if (i != 0)
435              memory_info.segment_pool[i].previous=
436                (&memory_info.segment_pool[i-1]);
437            if (i != (MaxSegments-1))
438              memory_info.segment_pool[i].next=(&memory_info.segment_pool[i+1]);
439          }
440          free_segments=(&memory_info.segment_pool[0]);
441        }
442      UnlockSemaphoreInfo(memory_semaphore);
443    }
444  LockSemaphoreInfo(memory_semaphore);
445  memory=AcquireBlock(size == 0 ? 1UL : size);
446  if (memory == (void *) NULL)
447    {
448      if (ExpandHeap(size == 0 ? 1UL : size) != MagickFalse)
449        memory=AcquireBlock(size == 0 ? 1UL : size);
450    }
451  UnlockSemaphoreInfo(memory_semaphore);
452#endif
453  return(memory);
454}
455
456/*
457%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
458%                                                                             %
459%                                                                             %
460%                                                                             %
461%   A c q u i r e Q u a n t u m M e m o r y                                   %
462%                                                                             %
463%                                                                             %
464%                                                                             %
465%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
466%
467%  AcquireQuantumMemory() returns a pointer to a block of memory at least
468%  count * quantum bytes suitably aligned for any use.
469%
470%  The format of the AcquireQuantumMemory method is:
471%
472%      void *AcquireQuantumMemory(const size_t count,const size_t quantum)
473%
474%  A description of each parameter follows:
475%
476%    o count: the number of quantum elements to allocate.
477%
478%    o quantum: the number of bytes in each quantum.
479%
480*/
481MagickExport void *AcquireQuantumMemory(const size_t count,const size_t quantum)
482{
483  size_t
484    size;
485
486  size=count*quantum;
487  if ((count == 0) || (quantum != (size/count)))
488    {
489      errno=ENOMEM;
490      return((void *) NULL);
491    }
492  return(AcquireMagickMemory(size));
493}
494
495/*
496%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
497%                                                                             %
498%                                                                             %
499%                                                                             %
500%   C o p y M a g i c k M e m o r y                                           %
501%                                                                             %
502%                                                                             %
503%                                                                             %
504%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
505%
506%  CopyMagickMemory() copies size bytes from memory area source to the
507%  destination.  Copying between objects that overlap will take place
508%  correctly.  It returns destination.
509%
510%  The format of the CopyMagickMemory method is:
511%
512%      void *CopyMagickMemory(void *destination,const void *source,
513%        const size_t size)
514%
515%  A description of each parameter follows:
516%
517%    o destination: the destination.
518%
519%    o source: the source.
520%
521%    o size: the size of the memory in bytes to allocate.
522%
523*/
524MagickExport void *CopyMagickMemory(void *destination,const void *source,
525  const size_t size)
526{
527  register const unsigned char
528    *p;
529
530  register unsigned char
531    *q;
532
533  assert(destination != (void *) NULL);
534  assert(source != (const void *) NULL);
535  p=(const unsigned char *) source;
536  q=(unsigned char *) destination;
537  if (((q+size) < p) || (q > (p+size)))
538    switch (size)
539    {
540      default: return(memcpy(destination,source,size));
541      case 8: *q++=(*p++);
542      case 7: *q++=(*p++);
543      case 6: *q++=(*p++);
544      case 5: *q++=(*p++);
545      case 4: *q++=(*p++);
546      case 3: *q++=(*p++);
547      case 2: *q++=(*p++);
548      case 1: *q++=(*p++);
549      case 0: return(destination);
550    }
551  return(memmove(destination,source,size));
552}
553
554/*
555%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
556%                                                                             %
557%                                                                             %
558%                                                                             %
559+   D e s t r o y M a g i c k M e m o r y                                     %
560%                                                                             %
561%                                                                             %
562%                                                                             %
563%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
564%
565%  DestroyMagickMemory() deallocates memory associated with the memory manager.
566%
567%  The format of the DestroyMagickMemory method is:
568%
569%      DestroyMagickMemory(void)
570%
571*/
572MagickExport void DestroyMagickMemory(void)
573{
574#if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
575  register ssize_t
576    i;
577
578  if (memory_semaphore == (SemaphoreInfo *) NULL)
579    AcquireSemaphoreInfo(&memory_semaphore);
580  LockSemaphoreInfo(memory_semaphore);
581  UnlockSemaphoreInfo(memory_semaphore);
582  for (i=0; i < (ssize_t) memory_info.number_segments; i++)
583    if (memory_info.segments[i]->mapped == MagickFalse)
584      memory_methods.destroy_memory_handler(
585        memory_info.segments[i]->allocation);
586    else
587      (void) UnmapBlob(memory_info.segments[i]->allocation,
588        memory_info.segments[i]->length);
589  free_segments=(DataSegmentInfo *) NULL;
590  (void) ResetMagickMemory(&memory_info,0,sizeof(memory_info));
591  DestroySemaphoreInfo(&memory_semaphore);
592#endif
593}
594
595#if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
596/*
597%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
598%                                                                             %
599%                                                                             %
600%                                                                             %
601+   E x p a n d H e a p                                                       %
602%                                                                             %
603%                                                                             %
604%                                                                             %
605%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
606%
607%  ExpandHeap() get more memory from the system.  It returns MagickTrue on
608%  success otherwise MagickFalse.
609%
610%  The format of the ExpandHeap method is:
611%
612%      MagickBooleanType ExpandHeap(size_t size)
613%
614%  A description of each parameter follows:
615%
616%    o size: the size of the memory in bytes we require.
617%
618*/
619static MagickBooleanType ExpandHeap(size_t size)
620{
621  DataSegmentInfo
622    *segment_info;
623
624  MagickBooleanType
625    mapped;
626
627  register ssize_t
628    i;
629
630  register void
631    *block;
632
633  size_t
634    blocksize;
635
636  void
637    *segment;
638
639  blocksize=((size+12*sizeof(size_t))+SegmentSize-1) & -SegmentSize;
640  assert(memory_info.number_segments < MaxSegments);
641  segment=MapBlob(-1,IOMode,0,blocksize);
642  mapped=segment != (void *) NULL ? MagickTrue : MagickFalse;
643  if (segment == (void *) NULL)
644    segment=(void *) memory_methods.acquire_memory_handler(blocksize);
645  if (segment == (void *) NULL)
646    return(MagickFalse);
647  segment_info=(DataSegmentInfo *) free_segments;
648  free_segments=segment_info->next;
649  segment_info->mapped=mapped;
650  segment_info->length=blocksize;
651  segment_info->allocation=segment;
652  segment_info->bound=(char *) segment+blocksize;
653  i=(ssize_t) memory_info.number_segments-1;
654  for ( ; (i >= 0) && (memory_info.segments[i]->allocation > segment); i--)
655    memory_info.segments[i+1]=memory_info.segments[i];
656  memory_info.segments[i+1]=segment_info;
657  memory_info.number_segments++;
658  size=blocksize-12*sizeof(size_t);
659  block=(char *) segment_info->allocation+4*sizeof(size_t);
660  *BlockHeader(block)=size | PreviousBlockBit;
661  *BlockFooter(block,size)=size;
662  InsertFreeBlock(block,AllocationPolicy(size));
663  block=NextBlock(block);
664  assert(block < segment_info->bound);
665  *BlockHeader(block)=2*sizeof(size_t);
666  *BlockHeader(NextBlock(block))=PreviousBlockBit;
667  return(MagickTrue);
668}
669#endif
670
671/*
672%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
673%                                                                             %
674%                                                                             %
675%                                                                             %
676%   G e t M a g i c k M e m o r y M e t h o d s                               %
677%                                                                             %
678%                                                                             %
679%                                                                             %
680%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
681%
682%  GetMagickMemoryMethods() gets the methods to acquire, resize, and destroy
683%  memory.
684%
685%  The format of the GetMagickMemoryMethods() method is:
686%
687%      void GetMagickMemoryMethods(AcquireMemoryHandler *acquire_memory_handler,
688%        ResizeMemoryHandler *resize_memory_handler,
689%        DestroyMemoryHandler *destroy_memory_handler)
690%
691%  A description of each parameter follows:
692%
693%    o acquire_memory_handler: method to acquire memory (e.g. malloc).
694%
695%    o resize_memory_handler: method to resize memory (e.g. realloc).
696%
697%    o destroy_memory_handler: method to destroy memory (e.g. free).
698%
699*/
700MagickExport void GetMagickMemoryMethods(
701  AcquireMemoryHandler *acquire_memory_handler,
702  ResizeMemoryHandler *resize_memory_handler,
703  DestroyMemoryHandler *destroy_memory_handler)
704{
705  assert(acquire_memory_handler != (AcquireMemoryHandler *) NULL);
706  assert(resize_memory_handler != (ResizeMemoryHandler *) NULL);
707  assert(destroy_memory_handler != (DestroyMemoryHandler *) NULL);
708  *acquire_memory_handler=memory_methods.acquire_memory_handler;
709  *resize_memory_handler=memory_methods.resize_memory_handler;
710  *destroy_memory_handler=memory_methods.destroy_memory_handler;
711}
712
713/*
714%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
715%                                                                             %
716%                                                                             %
717%                                                                             %
718%   R e l i n q u i s h A l i g n e d M e m o r y                             %
719%                                                                             %
720%                                                                             %
721%                                                                             %
722%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
723%
724%  RelinquishAlignedMemory() frees memory acquired with AcquireAlignedMemory()
725%  or reuse.
726%
727%  The format of the RelinquishAlignedMemory method is:
728%
729%      void *RelinquishAlignedMemory(void *memory)
730%
731%  A description of each parameter follows:
732%
733%    o memory: A pointer to a block of memory to free for reuse.
734%
735*/
736MagickExport void *RelinquishAlignedMemory(void *memory)
737{
738  if (memory == (void *) NULL)
739    return((void *) NULL);
740#if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
741  free(memory);
742#elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
743  _aligned_free(memory);
744#else
745  free(*((void **) memory-1));
746#endif
747  return(NULL);
748}
749
750/*
751%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
752%                                                                             %
753%                                                                             %
754%                                                                             %
755%   R e l i n q u i s h M a g i c k M e m o r y                               %
756%                                                                             %
757%                                                                             %
758%                                                                             %
759%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
760%
761%  RelinquishMagickMemory() frees memory acquired with AcquireMagickMemory()
762%  or AcquireQuantumMemory() for reuse.
763%
764%  The format of the RelinquishMagickMemory method is:
765%
766%      void *RelinquishMagickMemory(void *memory)
767%
768%  A description of each parameter follows:
769%
770%    o memory: A pointer to a block of memory to free for reuse.
771%
772*/
773MagickExport void *RelinquishMagickMemory(void *memory)
774{
775  if (memory == (void *) NULL)
776    return((void *) NULL);
777#if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
778  memory_methods.destroy_memory_handler(memory);
779#else
780  LockSemaphoreInfo(memory_semaphore);
781  assert((SizeOfBlock(memory) % (4*sizeof(size_t))) == 0);
782  assert((*BlockHeader(NextBlock(memory)) & PreviousBlockBit) != 0);
783  if ((*BlockHeader(memory) & PreviousBlockBit) == 0)
784    {
785      void
786        *previous;
787
788      /*
789        Coalesce with previous adjacent block.
790      */
791      previous=PreviousBlock(memory);
792      RemoveFreeBlock(previous,AllocationPolicy(SizeOfBlock(previous)));
793      *BlockHeader(previous)=(SizeOfBlock(previous)+SizeOfBlock(memory)) |
794        (*BlockHeader(previous) & ~SizeMask);
795      memory=previous;
796    }
797  if ((*BlockHeader(NextBlock(NextBlock(memory))) & PreviousBlockBit) == 0)
798    {
799      void
800        *next;
801
802      /*
803        Coalesce with next adjacent block.
804      */
805      next=NextBlock(memory);
806      RemoveFreeBlock(next,AllocationPolicy(SizeOfBlock(next)));
807      *BlockHeader(memory)=(SizeOfBlock(memory)+SizeOfBlock(next)) |
808        (*BlockHeader(memory) & ~SizeMask);
809    }
810  *BlockFooter(memory,SizeOfBlock(memory))=SizeOfBlock(memory);
811  *BlockHeader(NextBlock(memory))&=(~PreviousBlockBit);
812  InsertFreeBlock(memory,AllocationPolicy(SizeOfBlock(memory)));
813  UnlockSemaphoreInfo(memory_semaphore);
814#endif
815  return((void *) NULL);
816}
817
818/*
819%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
820%                                                                             %
821%                                                                             %
822%                                                                             %
823%   R e s e t M a g i c k M e m o r y                                         %
824%                                                                             %
825%                                                                             %
826%                                                                             %
827%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
828%
829%  ResetMagickMemory() fills the first size bytes of the memory area pointed to
830%  by memory with the constant byte c.
831%
832%  The format of the ResetMagickMemory method is:
833%
834%      void *ResetMagickMemory(void *memory,int byte,const size_t size)
835%
836%  A description of each parameter follows:
837%
838%    o memory: a pointer to a memory allocation.
839%
840%    o byte: set the memory to this value.
841%
842%    o size: size of the memory to reset.
843%
844*/
845MagickExport void *ResetMagickMemory(void *memory,int byte,const size_t size)
846{
847  assert(memory != (void *) NULL);
848  return(memset(memory,byte,size));
849}
850
851/*
852%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
853%                                                                             %
854%                                                                             %
855%                                                                             %
856%   R e s i z e M a g i c k M e m o r y                                       %
857%                                                                             %
858%                                                                             %
859%                                                                             %
860%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
861%
862%  ResizeMagickMemory() changes the size of the memory and returns a pointer to
863%  the (possibly moved) block.  The contents will be unchanged up to the
864%  lesser of the new and old sizes.
865%
866%  The format of the ResizeMagickMemory method is:
867%
868%      void *ResizeMagickMemory(void *memory,const size_t size)
869%
870%  A description of each parameter follows:
871%
872%    o memory: A pointer to a memory allocation.
873%
874%    o size: the new size of the allocated memory.
875%
876*/
877
878#if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
879static inline void *ResizeBlock(void *block,size_t size)
880{
881  register void
882    *memory;
883
884  if (block == (void *) NULL)
885    return(AcquireBlock(size));
886  memory=AcquireBlock(size);
887  if (memory == (void *) NULL)
888    return((void *) NULL);
889  if (size <= (SizeOfBlock(block)-sizeof(size_t)))
890    (void) memcpy(memory,block,size);
891  else
892    (void) memcpy(memory,block,SizeOfBlock(block)-sizeof(size_t));
893  memory_info.allocation+=size;
894  return(memory);
895}
896#endif
897
898MagickExport void *ResizeMagickMemory(void *memory,const size_t size)
899{
900  register void
901    *block;
902
903  if (memory == (void *) NULL)
904    return(AcquireMagickMemory(size));
905#if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
906  block=memory_methods.resize_memory_handler(memory,size == 0 ? 1UL : size);
907  if (block == (void *) NULL)
908    memory=RelinquishMagickMemory(memory);
909#else
910  LockSemaphoreInfo(memory_semaphore);
911  block=ResizeBlock(memory,size == 0 ? 1UL : size);
912  if (block == (void *) NULL)
913    {
914      if (ExpandHeap(size == 0 ? 1UL : size) == MagickFalse)
915        {
916          UnlockSemaphoreInfo(memory_semaphore);
917          memory=RelinquishMagickMemory(memory);
918          ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
919        }
920      block=ResizeBlock(memory,size == 0 ? 1UL : size);
921      assert(block != (void *) NULL);
922    }
923  UnlockSemaphoreInfo(memory_semaphore);
924  memory=RelinquishMagickMemory(memory);
925#endif
926  return(block);
927}
928
929/*
930%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
931%                                                                             %
932%                                                                             %
933%                                                                             %
934%   R e s i z e Q u a n t u m M e m o r y                                     %
935%                                                                             %
936%                                                                             %
937%                                                                             %
938%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
939%
940%  ResizeQuantumMemory() changes the size of the memory and returns a pointer
941%  to the (possibly moved) block.  The contents will be unchanged up to the
942%  lesser of the new and old sizes.
943%
944%  The format of the ResizeQuantumMemory method is:
945%
946%      void *ResizeQuantumMemory(void *memory,const size_t count,
947%        const size_t quantum)
948%
949%  A description of each parameter follows:
950%
951%    o memory: A pointer to a memory allocation.
952%
953%    o count: the number of quantum elements to allocate.
954%
955%    o quantum: the number of bytes in each quantum.
956%
957*/
958MagickExport void *ResizeQuantumMemory(void *memory,const size_t count,
959  const size_t quantum)
960{
961  size_t
962    size;
963
964  size=count*quantum;
965  if ((count == 0) || (quantum != (size/count)))
966    {
967      memory=RelinquishMagickMemory(memory);
968      errno=ENOMEM;
969      return((void *) NULL);
970    }
971  return(ResizeMagickMemory(memory,size));
972}
973
974/*
975%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
976%                                                                             %
977%                                                                             %
978%                                                                             %
979%   S e t M a g i c k M e m o r y M e t h o d s                               %
980%                                                                             %
981%                                                                             %
982%                                                                             %
983%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
984%
985%  SetMagickMemoryMethods() sets the methods to acquire, resize, and destroy
986%  memory. Your custom memory methods must be set prior to the
987%  MagickCoreGenesis() method.
988%
989%  The format of the SetMagickMemoryMethods() method is:
990%
991%      SetMagickMemoryMethods(AcquireMemoryHandler acquire_memory_handler,
992%        ResizeMemoryHandler resize_memory_handler,
993%        DestroyMemoryHandler destroy_memory_handler)
994%
995%  A description of each parameter follows:
996%
997%    o acquire_memory_handler: method to acquire memory (e.g. malloc).
998%
999%    o resize_memory_handler: method to resize memory (e.g. realloc).
1000%
1001%    o destroy_memory_handler: method to destroy memory (e.g. free).
1002%
1003*/
1004MagickExport void SetMagickMemoryMethods(
1005  AcquireMemoryHandler acquire_memory_handler,
1006  ResizeMemoryHandler resize_memory_handler,
1007  DestroyMemoryHandler destroy_memory_handler)
1008{
1009  /*
1010    Set memory methods.
1011  */
1012  if (acquire_memory_handler != (AcquireMemoryHandler) NULL)
1013    memory_methods.acquire_memory_handler=acquire_memory_handler;
1014  if (resize_memory_handler != (ResizeMemoryHandler) NULL)
1015    memory_methods.resize_memory_handler=resize_memory_handler;
1016  if (destroy_memory_handler != (DestroyMemoryHandler) NULL)
1017    memory_methods.destroy_memory_handler=destroy_memory_handler;
1018}
1019