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