MagickCore  6.7.5
memory.c
Go to the documentation of this file.
00001 /*
00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00003 %                                                                             %
00004 %                                                                             %
00005 %                                                                             %
00006 %                    M   M  EEEEE  M   M   OOO   RRRR   Y   Y                 %
00007 %                    MM MM  E      MM MM  O   O  R   R   Y Y                  %
00008 %                    M M M  EEE    M M M  O   O  RRRR     Y                   %
00009 %                    M   M  E      M   M  O   O  R R      Y                   %
00010 %                    M   M  EEEEE  M   M   OOO   R  R     Y                   %
00011 %                                                                             %
00012 %                                                                             %
00013 %                     MagickCore Memory Allocation Methods                    %
00014 %                                                                             %
00015 %                              Software Design                                %
00016 %                                John Cristy                                  %
00017 %                                 July 1998                                   %
00018 %                                                                             %
00019 %                                                                             %
00020 %  Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization      %
00021 %  dedicated to making software imaging solutions freely available.           %
00022 %                                                                             %
00023 %  You may not use this file except in compliance with the License.  You may  %
00024 %  obtain a copy of the License at                                            %
00025 %                                                                             %
00026 %    http://www.imagemagick.org/script/license.php                            %
00027 %                                                                             %
00028 %  Unless required by applicable law or agreed to in writing, software        %
00029 %  distributed under the License is distributed on an "AS IS" BASIS,          %
00030 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
00031 %  See the License for the specific language governing permissions and        %
00032 %  limitations under the License.                                             %
00033 %                                                                             %
00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00035 %
00036 %  Segregate our memory requirements from any program that calls our API.  This
00037 %  should help reduce the risk of others changing our program state or causing
00038 %  memory corruption.
00039 %
00040 %  Our custom memory allocation manager implements a best-fit allocation policy
00041 %  using segregated free lists.  It uses a linear distribution of size classes
00042 %  for lower sizes and a power of two distribution of size classes at higher
00043 %  sizes.  It is based on the paper, "Fast Memory Allocation using Lazy Fits."
00044 %  written by Yoo C. Chung.
00045 %
00046 %  By default, ANSI memory methods are called (e.g. malloc).  Use the
00047 %  custom memory allocator by defining MAGICKCORE_ZERO_CONFIGURATION_SUPPORT
00048 %  to allocate memory with private anonymous mapping rather than from the
00049 %  heap.
00050 %
00051 */
00052 
00053 /*
00054   Include declarations.
00055 */
00056 #include "MagickCore/studio.h"
00057 #include "MagickCore/blob.h"
00058 #include "MagickCore/blob-private.h"
00059 #include "MagickCore/exception.h"
00060 #include "MagickCore/exception-private.h"
00061 #include "MagickCore/memory_.h"
00062 #include "MagickCore/semaphore.h"
00063 #include "MagickCore/string_.h"
00064 
00065 /*
00066   Define declarations.
00067 */
00068 #define BlockFooter(block,size) \
00069   ((size_t *) ((char *) (block)+(size)-2*sizeof(size_t)))
00070 #define BlockHeader(block)  ((size_t *) (block)-1)
00071 #define BlockSize  4096
00072 #define BlockThreshold  1024
00073 #define AlignedSize  (16*sizeof(void *))
00074 #define MaxBlockExponent  16
00075 #define MaxBlocks ((BlockThreshold/(4*sizeof(size_t)))+MaxBlockExponent+1)
00076 #define MaxSegments  1024
00077 #define MemoryGuard  ((0xdeadbeef << 31)+0xdeafdeed)
00078 #define NextBlock(block)  ((char *) (block)+SizeOfBlock(block))
00079 #define NextBlockInList(block)  (*(void **) (block))
00080 #define PreviousBlock(block)  ((char *) (block)-(*((size_t *) (block)-2)))
00081 #define PreviousBlockBit  0x01
00082 #define PreviousBlockInList(block)  (*((void **) (block)+1))
00083 #define SegmentSize  (2*1024*1024)
00084 #define SizeMask  (~0x01)
00085 #define SizeOfBlock(block)  (*BlockHeader(block) & SizeMask)
00086 
00087 /*
00088   Typedef declarations.
00089 */
00090 typedef struct _DataSegmentInfo
00091 {
00092   void
00093     *allocation,
00094     *bound;
00095 
00096   MagickBooleanType
00097     mapped;
00098 
00099   size_t
00100     length;
00101 
00102   struct _DataSegmentInfo
00103     *previous,
00104     *next;
00105 } DataSegmentInfo;
00106 
00107 typedef struct _MemoryInfo
00108 {
00109   size_t
00110     allocation;
00111 
00112   void
00113     *blocks[MaxBlocks+1];
00114 
00115   size_t
00116     number_segments;
00117 
00118   DataSegmentInfo
00119     *segments[MaxSegments],
00120     segment_pool[MaxSegments];
00121 } MemoryInfo;
00122 
00123 typedef struct _MagickMemoryMethods
00124 {
00125   AcquireMemoryHandler
00126     acquire_memory_handler;
00127 
00128   ResizeMemoryHandler
00129     resize_memory_handler;
00130 
00131   DestroyMemoryHandler
00132     destroy_memory_handler;
00133 } MagickMemoryMethods;
00134 
00135 
00136 /*
00137   Global declarations.
00138 */
00139 static MagickMemoryMethods
00140   memory_methods =
00141   {
00142     (AcquireMemoryHandler) malloc,
00143     (ResizeMemoryHandler) realloc,
00144     (DestroyMemoryHandler) free
00145   };
00146 
00147 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
00148 static MemoryInfo
00149   memory_info;
00150 
00151 static SemaphoreInfo
00152   *memory_semaphore = (SemaphoreInfo *) NULL;
00153 
00154 static volatile DataSegmentInfo
00155   *free_segments = (DataSegmentInfo *) NULL;
00156 
00157 /*
00158   Forward declarations.
00159 */
00160 static MagickBooleanType
00161   ExpandHeap(size_t);
00162 #endif
00163 
00164 /*
00165 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00166 %                                                                             %
00167 %                                                                             %
00168 %                                                                             %
00169 %   A c q u i r e A l i g n e d M e m o r y                                   %
00170 %                                                                             %
00171 %                                                                             %
00172 %                                                                             %
00173 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00174 %
00175 %  AcquireAlignedMemory() returns a pointer to a block of memory at least size
00176 %  bytes whose address is a multiple of 16*sizeof(void *).
00177 %
00178 %  The format of the AcquireAlignedMemory method is:
00179 %
00180 %      void *AcquireAlignedMemory(const size_t count,const size_t quantum)
00181 %
00182 %  A description of each parameter follows:
00183 %
00184 %    o count: the number of quantum elements to allocate.
00185 %
00186 %    o quantum: the number of bytes in each quantum.
00187 %
00188 */
00189 
00190 static inline size_t MagickMax(const size_t x,const size_t y)
00191 {
00192   if (x > y)
00193     return(x);
00194   return(y);
00195 }
00196 
00197 MagickExport void *AcquireAlignedMemory(const size_t count,const size_t quantum)
00198 {
00199   size_t
00200     size;
00201 
00202   size=count*quantum;
00203   if ((count == 0) || (quantum != (size/count)))
00204     {
00205       errno=ENOMEM;
00206       return((void *) NULL);
00207     }
00208 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
00209   {
00210     void
00211       *memory;
00212 
00213     if (posix_memalign(&memory,AlignedSize,MagickMax(size,AlignedSize)) == 0)
00214       return(memory);
00215   }
00216 #endif
00217   return(malloc(MagickMax(size,AlignedSize)));
00218 }
00219 
00220 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
00221 /*
00222 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00223 %                                                                             %
00224 %                                                                             %
00225 %                                                                             %
00226 +   A c q u i r e B l o c k                                                   %
00227 %                                                                             %
00228 %                                                                             %
00229 %                                                                             %
00230 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00231 %
00232 %  AcquireBlock() returns a pointer to a block of memory at least size bytes
00233 %  suitably aligned for any use.
00234 %
00235 %  The format of the AcquireBlock method is:
00236 %
00237 %      void *AcquireBlock(const size_t size)
00238 %
00239 %  A description of each parameter follows:
00240 %
00241 %    o size: the size of the memory in bytes to allocate.
00242 %
00243 */
00244 
00245 static inline size_t AllocationPolicy(size_t size)
00246 {
00247   register size_t
00248     blocksize;
00249 
00250   /*
00251     The linear distribution.
00252   */
00253   assert(size != 0);
00254   assert(size % (4*sizeof(size_t)) == 0);
00255   if (size <= BlockThreshold)
00256     return(size/(4*sizeof(size_t)));
00257   /*
00258     Check for the largest block size.
00259   */
00260   if (size > (size_t) (BlockThreshold*(1L << (MaxBlockExponent-1L))))
00261     return(MaxBlocks-1L);
00262   /*
00263     Otherwise use a power of two distribution.
00264   */
00265   blocksize=BlockThreshold/(4*sizeof(size_t));
00266   for ( ; size > BlockThreshold; size/=2)
00267     blocksize++;
00268   assert(blocksize > (BlockThreshold/(4*sizeof(size_t))));
00269   assert(blocksize < (MaxBlocks-1L));
00270   return(blocksize);
00271 }
00272 
00273 static inline void InsertFreeBlock(void *block,const size_t i)
00274 {
00275   register void
00276     *next,
00277     *previous;
00278 
00279   size_t
00280     size;
00281 
00282   size=SizeOfBlock(block);
00283   previous=(void *) NULL;
00284   next=memory_info.blocks[i];
00285   while ((next != (void *) NULL) && (SizeOfBlock(next) < size))
00286   {
00287     previous=next;
00288     next=NextBlockInList(next);
00289   }
00290   PreviousBlockInList(block)=previous;
00291   NextBlockInList(block)=next;
00292   if (previous != (void *) NULL)
00293     NextBlockInList(previous)=block;
00294   else
00295     memory_info.blocks[i]=block;
00296   if (next != (void *) NULL)
00297     PreviousBlockInList(next)=block;
00298 }
00299 
00300 static inline void RemoveFreeBlock(void *block,const size_t i)
00301 {
00302   register void
00303     *next,
00304     *previous;
00305 
00306   next=NextBlockInList(block);
00307   previous=PreviousBlockInList(block);
00308   if (previous == (void *) NULL)
00309     memory_info.blocks[i]=next;
00310   else
00311     NextBlockInList(previous)=next;
00312   if (next != (void *) NULL)
00313     PreviousBlockInList(next)=previous;
00314 }
00315 
00316 static void *AcquireBlock(size_t size)
00317 {
00318   register size_t
00319     i;
00320 
00321   register void
00322     *block;
00323 
00324   /*
00325     Find free block.
00326   */
00327   size=(size_t) (size+sizeof(size_t)+6*sizeof(size_t)-1) & -(4U*sizeof(size_t));
00328   i=AllocationPolicy(size);
00329   block=memory_info.blocks[i];
00330   while ((block != (void *) NULL) && (SizeOfBlock(block) < size))
00331     block=NextBlockInList(block);
00332   if (block == (void *) NULL)
00333     {
00334       i++;
00335       while (memory_info.blocks[i] == (void *) NULL)
00336         i++;
00337       block=memory_info.blocks[i];
00338       if (i >= MaxBlocks)
00339         return((void *) NULL);
00340     }
00341   assert((*BlockHeader(NextBlock(block)) & PreviousBlockBit) == 0);
00342   assert(SizeOfBlock(block) >= size);
00343   RemoveFreeBlock(block,AllocationPolicy(SizeOfBlock(block)));
00344   if (SizeOfBlock(block) > size)
00345     {
00346       size_t
00347         blocksize;
00348 
00349       void
00350         *next;
00351 
00352       /*
00353         Split block.
00354       */
00355       next=(char *) block+size;
00356       blocksize=SizeOfBlock(block)-size;
00357       *BlockHeader(next)=blocksize;
00358       *BlockFooter(next,blocksize)=blocksize;
00359       InsertFreeBlock(next,AllocationPolicy(blocksize));
00360       *BlockHeader(block)=size | (*BlockHeader(block) & ~SizeMask);
00361     }
00362   assert(size == SizeOfBlock(block));
00363   *BlockHeader(NextBlock(block))|=PreviousBlockBit;
00364   memory_info.allocation+=size;
00365   return(block);
00366 }
00367 #endif
00368 
00369 /*
00370 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00371 %                                                                             %
00372 %                                                                             %
00373 %                                                                             %
00374 %   A c q u i r e M a g i c k M e m o r y                                     %
00375 %                                                                             %
00376 %                                                                             %
00377 %                                                                             %
00378 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00379 %
00380 %  AcquireMagickMemory() returns a pointer to a block of memory at least size
00381 %  bytes suitably aligned for any use.
00382 %
00383 %  The format of the AcquireMagickMemory method is:
00384 %
00385 %      void *AcquireMagickMemory(const size_t size)
00386 %
00387 %  A description of each parameter follows:
00388 %
00389 %    o size: the size of the memory in bytes to allocate.
00390 %
00391 */
00392 MagickExport void *AcquireMagickMemory(const size_t size)
00393 {
00394   register void
00395     *memory;
00396 
00397 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
00398   memory=memory_methods.acquire_memory_handler(size == 0 ? 1UL : size);
00399 #else
00400   if (memory_semaphore == (SemaphoreInfo *) NULL)
00401     AcquireSemaphoreInfo(&memory_semaphore);
00402   if (free_segments == (DataSegmentInfo *) NULL)
00403     {
00404       LockSemaphoreInfo(memory_semaphore);
00405       if (free_segments == (DataSegmentInfo *) NULL)
00406         {
00407           register ssize_t
00408             i;
00409 
00410           assert(2*sizeof(size_t) > (size_t) (~SizeMask));
00411           (void) ResetMagickMemory(&memory_info,0,sizeof(memory_info));
00412           memory_info.allocation=SegmentSize;
00413           memory_info.blocks[MaxBlocks]=(void *) (-1);
00414           for (i=0; i < MaxSegments; i++)
00415           {
00416             if (i != 0)
00417               memory_info.segment_pool[i].previous=
00418                 (&memory_info.segment_pool[i-1]);
00419             if (i != (MaxSegments-1))
00420               memory_info.segment_pool[i].next=(&memory_info.segment_pool[i+1]);
00421           }
00422           free_segments=(&memory_info.segment_pool[0]);
00423         }
00424       UnlockSemaphoreInfo(memory_semaphore);
00425     }
00426   LockSemaphoreInfo(memory_semaphore);
00427   memory=AcquireBlock(size == 0 ? 1UL : size);
00428   if (memory == (void *) NULL)
00429     {
00430       if (ExpandHeap(size == 0 ? 1UL : size) != MagickFalse)
00431         memory=AcquireBlock(size == 0 ? 1UL : size);
00432     }
00433   UnlockSemaphoreInfo(memory_semaphore);
00434 #endif
00435   return(memory);
00436 }
00437 
00438 /*
00439 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00440 %                                                                             %
00441 %                                                                             %
00442 %                                                                             %
00443 %   A c q u i r e Q u a n t u m M e m o r y                                   %
00444 %                                                                             %
00445 %                                                                             %
00446 %                                                                             %
00447 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00448 %
00449 %  AcquireQuantumMemory() returns a pointer to a block of memory at least
00450 %  count * quantum bytes suitably aligned for any use.
00451 %
00452 %  The format of the AcquireQuantumMemory method is:
00453 %
00454 %      void *AcquireQuantumMemory(const size_t count,const size_t quantum)
00455 %
00456 %  A description of each parameter follows:
00457 %
00458 %    o count: the number of quantum elements to allocate.
00459 %
00460 %    o quantum: the number of bytes in each quantum.
00461 %
00462 */
00463 MagickExport void *AcquireQuantumMemory(const size_t count,const size_t quantum)
00464 {
00465   size_t
00466     size;
00467 
00468   size=count*quantum;
00469   if ((count == 0) || (quantum != (size/count)))
00470     {
00471       errno=ENOMEM;
00472       return((void *) NULL);
00473     }
00474   return(AcquireMagickMemory(size));
00475 }
00476 
00477 /*
00478 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00479 %                                                                             %
00480 %                                                                             %
00481 %                                                                             %
00482 %   C o p y M a g i c k M e m o r y                                           %
00483 %                                                                             %
00484 %                                                                             %
00485 %                                                                             %
00486 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00487 %
00488 %  CopyMagickMemory() copies size bytes from memory area source to the
00489 %  destination.  Copying between objects that overlap will take place
00490 %  correctly.  It returns destination.
00491 %
00492 %  The format of the CopyMagickMemory method is:
00493 %
00494 %      void *CopyMagickMemory(void *destination,const void *source,
00495 %        const size_t size)
00496 %
00497 %  A description of each parameter follows:
00498 %
00499 %    o destination: the destination.
00500 %
00501 %    o source: the source.
00502 %
00503 %    o size: the size of the memory in bytes to allocate.
00504 %
00505 */
00506 MagickExport void *CopyMagickMemory(void *destination,const void *source,
00507   const size_t size)
00508 {
00509   register const unsigned char
00510     *p;
00511 
00512   register unsigned char
00513     *q;
00514 
00515   assert(destination != (void *) NULL);
00516   assert(source != (const void *) NULL);
00517   p=(const unsigned char *) source;
00518   q=(unsigned char *) destination;
00519   if (((q+size) < p) || (q > (p+size)))
00520     switch (size)
00521     {
00522       default: return(memcpy(destination,source,size));
00523       case 8: *q++=(*p++);
00524       case 7: *q++=(*p++);
00525       case 6: *q++=(*p++);
00526       case 5: *q++=(*p++);
00527       case 4: *q++=(*p++);
00528       case 3: *q++=(*p++);
00529       case 2: *q++=(*p++);
00530       case 1: *q++=(*p++);
00531       case 0: return(destination);
00532     }
00533   return(memmove(destination,source,size));
00534 }
00535 
00536 /*
00537 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00538 %                                                                             %
00539 %                                                                             %
00540 %                                                                             %
00541 +   D e s t r o y M a g i c k M e m o r y                                     %
00542 %                                                                             %
00543 %                                                                             %
00544 %                                                                             %
00545 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00546 %
00547 %  DestroyMagickMemory() deallocates memory associated with the memory manager.
00548 %
00549 %  The format of the DestroyMagickMemory method is:
00550 %
00551 %      DestroyMagickMemory(void)
00552 %
00553 */
00554 MagickExport void DestroyMagickMemory(void)
00555 {
00556 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
00557   register ssize_t
00558     i;
00559 
00560   if (memory_semaphore == (SemaphoreInfo *) NULL)
00561     AcquireSemaphoreInfo(&memory_semaphore);
00562   LockSemaphoreInfo(memory_semaphore);
00563   UnlockSemaphoreInfo(memory_semaphore);
00564   for (i=0; i < (ssize_t) memory_info.number_segments; i++)
00565     if (memory_info.segments[i]->mapped == MagickFalse)
00566       memory_methods.destroy_memory_handler(
00567         memory_info.segments[i]->allocation);
00568     else
00569       (void) UnmapBlob(memory_info.segments[i]->allocation,
00570         memory_info.segments[i]->length);
00571   free_segments=(DataSegmentInfo *) NULL;
00572   (void) ResetMagickMemory(&memory_info,0,sizeof(memory_info));
00573   DestroySemaphoreInfo(&memory_semaphore);
00574 #endif
00575 }
00576 
00577 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
00578 /*
00579 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00580 %                                                                             %
00581 %                                                                             %
00582 %                                                                             %
00583 +   E x p a n d H e a p                                                       %
00584 %                                                                             %
00585 %                                                                             %
00586 %                                                                             %
00587 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00588 %
00589 %  ExpandHeap() get more memory from the system.  It returns MagickTrue on
00590 %  success otherwise MagickFalse.
00591 %
00592 %  The format of the ExpandHeap method is:
00593 %
00594 %      MagickBooleanType ExpandHeap(size_t size)
00595 %
00596 %  A description of each parameter follows:
00597 %
00598 %    o size: the size of the memory in bytes we require.
00599 %
00600 */
00601 static MagickBooleanType ExpandHeap(size_t size)
00602 {
00603   DataSegmentInfo
00604     *segment_info;
00605 
00606   MagickBooleanType
00607     mapped;
00608 
00609   register ssize_t
00610     i;
00611 
00612   register void
00613     *block;
00614 
00615   size_t
00616     blocksize;
00617 
00618   void
00619     *segment;
00620 
00621   blocksize=((size+12*sizeof(size_t))+SegmentSize-1) & -SegmentSize;
00622   assert(memory_info.number_segments < MaxSegments);
00623   segment=MapBlob(-1,IOMode,0,blocksize);
00624   mapped=segment != (void *) NULL ? MagickTrue : MagickFalse;
00625   if (segment == (void *) NULL)
00626     segment=(void *) memory_methods.acquire_memory_handler(blocksize);
00627   if (segment == (void *) NULL)
00628     return(MagickFalse);
00629   segment_info=(DataSegmentInfo *) free_segments;
00630   free_segments=segment_info->next;
00631   segment_info->mapped=mapped;
00632   segment_info->length=blocksize;
00633   segment_info->allocation=segment;
00634   segment_info->bound=(char *) segment+blocksize;
00635   i=(ssize_t) memory_info.number_segments-1;
00636   for ( ; (i >= 0) && (memory_info.segments[i]->allocation > segment); i--)
00637     memory_info.segments[i+1]=memory_info.segments[i];
00638   memory_info.segments[i+1]=segment_info;
00639   memory_info.number_segments++;
00640   size=blocksize-12*sizeof(size_t);
00641   block=(char *) segment_info->allocation+4*sizeof(size_t);
00642   *BlockHeader(block)=size | PreviousBlockBit;
00643   *BlockFooter(block,size)=size;
00644   InsertFreeBlock(block,AllocationPolicy(size));
00645   block=NextBlock(block);
00646   assert(block < segment_info->bound);
00647   *BlockHeader(block)=2*sizeof(size_t);
00648   *BlockHeader(NextBlock(block))=PreviousBlockBit;
00649   return(MagickTrue);
00650 }
00651 #endif
00652 
00653 /*
00654 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00655 %                                                                             %
00656 %                                                                             %
00657 %                                                                             %
00658 %   G e t M a g i c k M e m o r y M e t h o d s                               %
00659 %                                                                             %
00660 %                                                                             %
00661 %                                                                             %
00662 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00663 %
00664 %  GetMagickMemoryMethods() gets the methods to acquire, resize, and destroy
00665 %  memory.
00666 %
00667 %  The format of the GetMagickMemoryMethods() method is:
00668 %
00669 %      void GetMagickMemoryMethods(AcquireMemoryHandler *acquire_memory_handler,
00670 %        ResizeMemoryHandler *resize_memory_handler,
00671 %        DestroyMemoryHandler *destroy_memory_handler)
00672 %
00673 %  A description of each parameter follows:
00674 %
00675 %    o acquire_memory_handler: method to acquire memory (e.g. malloc).
00676 %
00677 %    o resize_memory_handler: method to resize memory (e.g. realloc).
00678 %
00679 %    o destroy_memory_handler: method to destroy memory (e.g. free).
00680 %
00681 */
00682 MagickExport void GetMagickMemoryMethods(
00683   AcquireMemoryHandler *acquire_memory_handler,
00684   ResizeMemoryHandler *resize_memory_handler,
00685   DestroyMemoryHandler *destroy_memory_handler)
00686 {
00687   assert(acquire_memory_handler != (AcquireMemoryHandler *) NULL);
00688   assert(resize_memory_handler != (ResizeMemoryHandler *) NULL);
00689   assert(destroy_memory_handler != (DestroyMemoryHandler *) NULL);
00690   *acquire_memory_handler=memory_methods.acquire_memory_handler;
00691   *resize_memory_handler=memory_methods.resize_memory_handler;
00692   *destroy_memory_handler=memory_methods.destroy_memory_handler;
00693 }
00694 
00695 /*
00696 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00697 %                                                                             %
00698 %                                                                             %
00699 %                                                                             %
00700 %   R e l i n q u i s h A l i g n e d M e m o r y                             %
00701 %                                                                             %
00702 %                                                                             %
00703 %                                                                             %
00704 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00705 %
00706 %  RelinquishAlignedMemory() frees memory acquired with AcquireAlignedMemory()
00707 %  or reuse.
00708 %
00709 %  The format of the RelinquishAlignedMemory method is:
00710 %
00711 %      void *RelinquishAlignedMemory(void *memory)
00712 %
00713 %  A description of each parameter follows:
00714 %
00715 %    o memory: A pointer to a block of memory to free for reuse.
00716 %
00717 */
00718 MagickExport void *RelinquishAlignedMemory(void *memory)
00719 {
00720   if (memory == (void *) NULL)
00721     return((void *) NULL);
00722   free(memory);
00723   return((void *) NULL);
00724 }
00725 
00726 /*
00727 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00728 %                                                                             %
00729 %                                                                             %
00730 %                                                                             %
00731 %   R e l i n q u i s h M a g i c k M e m o r y                               %
00732 %                                                                             %
00733 %                                                                             %
00734 %                                                                             %
00735 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00736 %
00737 %  RelinquishMagickMemory() frees memory acquired with AcquireMagickMemory()
00738 %  or AcquireQuantumMemory() for reuse.
00739 %
00740 %  The format of the RelinquishMagickMemory method is:
00741 %
00742 %      void *RelinquishMagickMemory(void *memory)
00743 %
00744 %  A description of each parameter follows:
00745 %
00746 %    o memory: A pointer to a block of memory to free for reuse.
00747 %
00748 */
00749 MagickExport void *RelinquishMagickMemory(void *memory)
00750 {
00751   if (memory == (void *) NULL)
00752     return((void *) NULL);
00753 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
00754   memory_methods.destroy_memory_handler(memory);
00755 #else
00756   LockSemaphoreInfo(memory_semaphore);
00757   assert((SizeOfBlock(memory) % (4*sizeof(size_t))) == 0);
00758   assert((*BlockHeader(NextBlock(memory)) & PreviousBlockBit) != 0);
00759   if ((*BlockHeader(memory) & PreviousBlockBit) == 0)
00760     {
00761       void
00762         *previous;
00763 
00764       /*
00765         Coalesce with previous adjacent block.
00766       */
00767       previous=PreviousBlock(memory);
00768       RemoveFreeBlock(previous,AllocationPolicy(SizeOfBlock(previous)));
00769       *BlockHeader(previous)=(SizeOfBlock(previous)+SizeOfBlock(memory)) |
00770         (*BlockHeader(previous) & ~SizeMask);
00771       memory=previous;
00772     }
00773   if ((*BlockHeader(NextBlock(NextBlock(memory))) & PreviousBlockBit) == 0)
00774     {
00775       void
00776         *next;
00777 
00778       /*
00779         Coalesce with next adjacent block.
00780       */
00781       next=NextBlock(memory);
00782       RemoveFreeBlock(next,AllocationPolicy(SizeOfBlock(next)));
00783       *BlockHeader(memory)=(SizeOfBlock(memory)+SizeOfBlock(next)) |
00784         (*BlockHeader(memory) & ~SizeMask);
00785     }
00786   *BlockFooter(memory,SizeOfBlock(memory))=SizeOfBlock(memory);
00787   *BlockHeader(NextBlock(memory))&=(~PreviousBlockBit);
00788   InsertFreeBlock(memory,AllocationPolicy(SizeOfBlock(memory)));
00789   UnlockSemaphoreInfo(memory_semaphore);
00790 #endif
00791   return((void *) NULL);
00792 }
00793 
00794 /*
00795 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00796 %                                                                             %
00797 %                                                                             %
00798 %                                                                             %
00799 %   R e s e t M a g i c k M e m o r y                                         %
00800 %                                                                             %
00801 %                                                                             %
00802 %                                                                             %
00803 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00804 %
00805 %  ResetMagickMemory() fills the first size bytes of the memory area pointed to
00806 %  by memory with the constant byte c.
00807 %
00808 %  The format of the ResetMagickMemory method is:
00809 %
00810 %      void *ResetMagickMemory(void *memory,int byte,const size_t size)
00811 %
00812 %  A description of each parameter follows:
00813 %
00814 %    o memory: A pointer to a memory allocation.
00815 %
00816 %    o byte: Set the memory to this value.
00817 %
00818 %    o size: Size of the memory to reset.
00819 %
00820 */
00821 MagickExport void *ResetMagickMemory(void *memory,int byte,const size_t size)
00822 {
00823   assert(memory != (void *) NULL);
00824   return(memset(memory,byte,size));
00825 }
00826 
00827 /*
00828 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00829 %                                                                             %
00830 %                                                                             %
00831 %                                                                             %
00832 %   R e s i z e M a g i c k M e m o r y                                       %
00833 %                                                                             %
00834 %                                                                             %
00835 %                                                                             %
00836 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00837 %
00838 %  ResizeMagickMemory() changes the size of the memory and returns a pointer to
00839 %  the (possibly moved) block.  The contents will be unchanged up to the
00840 %  lesser of the new and old sizes.
00841 %
00842 %  The format of the ResizeMagickMemory method is:
00843 %
00844 %      void *ResizeMagickMemory(void *memory,const size_t size)
00845 %
00846 %  A description of each parameter follows:
00847 %
00848 %    o memory: A pointer to a memory allocation.
00849 %
00850 %    o size: the new size of the allocated memory.
00851 %
00852 */
00853 
00854 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
00855 static inline void *ResizeBlock(void *block,size_t size)
00856 {
00857   register void
00858     *memory;
00859 
00860   if (block == (void *) NULL)
00861     return(AcquireBlock(size));
00862   memory=AcquireBlock(size);
00863   if (memory == (void *) NULL)
00864     return((void *) NULL);
00865   if (size <= (SizeOfBlock(block)-sizeof(size_t)))
00866     (void) memcpy(memory,block,size);
00867   else
00868     (void) memcpy(memory,block,SizeOfBlock(block)-sizeof(size_t));
00869   memory_info.allocation+=size;
00870   return(memory);
00871 }
00872 #endif
00873 
00874 MagickExport void *ResizeMagickMemory(void *memory,const size_t size)
00875 {
00876   register void
00877     *block;
00878 
00879   if (memory == (void *) NULL)
00880     return(AcquireMagickMemory(size));
00881 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
00882   block=memory_methods.resize_memory_handler(memory,size == 0 ? 1UL : size);
00883   if (block == (void *) NULL)
00884     memory=RelinquishMagickMemory(memory);
00885 #else
00886   LockSemaphoreInfo(memory_semaphore);
00887   block=ResizeBlock(memory,size == 0 ? 1UL : size);
00888   if (block == (void *) NULL)
00889     {
00890       if (ExpandHeap(size == 0 ? 1UL : size) == MagickFalse)
00891         {
00892           UnlockSemaphoreInfo(memory_semaphore);
00893           memory=RelinquishMagickMemory(memory);
00894           ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00895         }
00896       block=ResizeBlock(memory,size == 0 ? 1UL : size);
00897       assert(block != (void *) NULL);
00898     }
00899   UnlockSemaphoreInfo(memory_semaphore);
00900   memory=RelinquishMagickMemory(memory);
00901 #endif
00902   return(block);
00903 }
00904 
00905 /*
00906 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00907 %                                                                             %
00908 %                                                                             %
00909 %                                                                             %
00910 %   R e s i z e Q u a n t u m M e m o r y                                     %
00911 %                                                                             %
00912 %                                                                             %
00913 %                                                                             %
00914 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00915 %
00916 %  ResizeQuantumMemory() changes the size of the memory and returns a pointer
00917 %  to the (possibly moved) block.  The contents will be unchanged up to the
00918 %  lesser of the new and old sizes.
00919 %
00920 %  The format of the ResizeQuantumMemory method is:
00921 %
00922 %      void *ResizeQuantumMemory(void *memory,const size_t count,
00923 %        const size_t quantum)
00924 %
00925 %  A description of each parameter follows:
00926 %
00927 %    o memory: A pointer to a memory allocation.
00928 %
00929 %    o count: the number of quantum elements to allocate.
00930 %
00931 %    o quantum: the number of bytes in each quantum.
00932 %
00933 */
00934 MagickExport void *ResizeQuantumMemory(void *memory,const size_t count,
00935   const size_t quantum)
00936 {
00937   size_t
00938     size;
00939 
00940   size=count*quantum;
00941   if ((count == 0) || (quantum != (size/count)))
00942     {
00943       memory=RelinquishMagickMemory(memory);
00944       errno=ENOMEM;
00945       return((void *) NULL);
00946     }
00947   return(ResizeMagickMemory(memory,size));
00948 }
00949 
00950 /*
00951 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00952 %                                                                             %
00953 %                                                                             %
00954 %                                                                             %
00955 %   S e t M a g i c k M e m o r y M e t h o d s                               %
00956 %                                                                             %
00957 %                                                                             %
00958 %                                                                             %
00959 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00960 %
00961 %  SetMagickMemoryMethods() sets the methods to acquire, resize, and destroy
00962 %  memory.
00963 %
00964 %  The format of the SetMagickMemoryMethods() method is:
00965 %
00966 %      SetMagickMemoryMethods(AcquireMemoryHandler acquire_memory_handler,
00967 %        ResizeMemoryHandler resize_memory_handler,
00968 %        DestroyMemoryHandler destroy_memory_handler)
00969 %
00970 %  A description of each parameter follows:
00971 %
00972 %    o acquire_memory_handler: method to acquire memory (e.g. malloc).
00973 %
00974 %    o resize_memory_handler: method to resize memory (e.g. realloc).
00975 %
00976 %    o destroy_memory_handler: method to destroy memory (e.g. free).
00977 %
00978 */
00979 MagickExport void SetMagickMemoryMethods(
00980   AcquireMemoryHandler acquire_memory_handler,
00981   ResizeMemoryHandler resize_memory_handler,
00982   DestroyMemoryHandler destroy_memory_handler)
00983 {
00984   /*
00985     Set memory methods.
00986   */
00987   if (acquire_memory_handler != (AcquireMemoryHandler) NULL)
00988     memory_methods.acquire_memory_handler=acquire_memory_handler;
00989   if (resize_memory_handler != (ResizeMemoryHandler) NULL)
00990     memory_methods.resize_memory_handler=resize_memory_handler;
00991   if (destroy_memory_handler != (DestroyMemoryHandler) NULL)
00992     memory_methods.destroy_memory_handler=destroy_memory_handler;
00993 }