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-2009 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_EMBEDDABLE_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 "magick/studio.h"
00057 #include "magick/blob.h"
00058 #include "magick/blob-private.h"
00059 #include "magick/exception.h"
00060 #include "magick/exception-private.h"
00061 #include "magick/memory_.h"
00062 #include "magick/semaphore.h"
00063 #include "magick/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_EMBEDDABLE_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 MagickExport void *AcquireAlignedMemory(const size_t count,const size_t quantum)
00190 {
00191   size_t
00192     size;
00193 
00194   size=count*quantum;
00195   if ((count == 0) || (quantum != (size/count)))
00196     {
00197       errno=ENOMEM;
00198       return((void *) NULL);
00199     }
00200 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
00201   {
00202     void
00203       *memory;
00204 
00205     if (posix_memalign(&memory,AlignedSize,size) == 0)
00206       return(memory);
00207   }
00208 #endif
00209   return(malloc(size));
00210 }
00211 
00212 #if defined(MAGICKCORE_EMBEDDABLE_SUPPORT)
00213 /*
00214 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00215 %                                                                             %
00216 %                                                                             %
00217 %                                                                             %
00218 +   A c q u i r e B l o c k                                                   %
00219 %                                                                             %
00220 %                                                                             %
00221 %                                                                             %
00222 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00223 %
00224 %  AcquireBlock() returns a pointer to a block of memory at least size bytes
00225 %  suitably aligned for any use.
00226 %
00227 %  The format of the AcquireBlock method is:
00228 %
00229 %      void *AcquireBlock(const size_t size)
00230 %
00231 %  A description of each parameter follows:
00232 %
00233 %    o size: the size of the memory in bytes to allocate.
00234 %
00235 */
00236 
00237 static inline size_t AllocationPolicy(size_t size)
00238 {
00239   register size_t
00240     blocksize;
00241 
00242   /*
00243     The linear distribution.
00244   */
00245   assert(size != 0);
00246   assert(size % (4*sizeof(size_t)) == 0);
00247   if (size <= BlockThreshold)
00248     return(size/(4*sizeof(size_t)));
00249   /*
00250     Check for the largest block size.
00251   */
00252   if (size > (size_t) (BlockThreshold*(1L << (MaxBlockExponent-1L))))
00253     return(MaxBlocks-1L);
00254   /*
00255     Otherwise use a power of two distribution.
00256   */
00257   blocksize=BlockThreshold/(4*sizeof(size_t));
00258   for ( ; size > BlockThreshold; size/=2)
00259     blocksize++;
00260   assert(blocksize > (BlockThreshold/(4*sizeof(size_t))));
00261   assert(blocksize < (MaxBlocks-1L));
00262   return(blocksize);
00263 }
00264 
00265 static inline void InsertFreeBlock(void *block,const size_t i)
00266 {
00267   register void
00268     *next,
00269     *previous;
00270 
00271   size_t
00272     size;
00273 
00274   size=SizeOfBlock(block);
00275   previous=(void *) NULL;
00276   next=memory_info.blocks[i];
00277   while ((next != (void *) NULL) && (SizeOfBlock(next) < size))
00278   {
00279     previous=next;
00280     next=NextBlockInList(next);
00281   }
00282   PreviousBlockInList(block)=previous;
00283   NextBlockInList(block)=next;
00284   if (previous != (void *) NULL)
00285     NextBlockInList(previous)=block;
00286   else
00287     memory_info.blocks[i]=block;
00288   if (next != (void *) NULL)
00289     PreviousBlockInList(next)=block;
00290 }
00291 
00292 static inline void RemoveFreeBlock(void *block,const size_t i)
00293 {
00294   register void
00295     *next,
00296     *previous;
00297 
00298   next=NextBlockInList(block);
00299   previous=PreviousBlockInList(block);
00300   if (previous == (void *) NULL)
00301     memory_info.blocks[i]=next;
00302   else
00303     NextBlockInList(previous)=next;
00304   if (next != (void *) NULL)
00305     PreviousBlockInList(next)=previous;
00306 }
00307 
00308 static void *AcquireBlock(size_t size)
00309 {
00310   register size_t
00311     i;
00312 
00313   register void
00314     *block;
00315 
00316   /*
00317     Find free block.
00318   */
00319   size=(size_t) (size+sizeof(size_t)+6*sizeof(size_t)-1) & -(4U*sizeof(size_t));
00320   i=AllocationPolicy(size);
00321   block=memory_info.blocks[i];
00322   while ((block != (void *) NULL) && (SizeOfBlock(block) < size))
00323     block=NextBlockInList(block);
00324   if (block == (void *) NULL)
00325     {
00326       i++;
00327       while (memory_info.blocks[i] == (void *) NULL)
00328         i++;
00329       block=memory_info.blocks[i];
00330       if (i >= MaxBlocks)
00331         return((void *) NULL);
00332     }
00333   assert((*BlockHeader(NextBlock(block)) & PreviousBlockBit) == 0);
00334   assert(SizeOfBlock(block) >= size);
00335   RemoveFreeBlock(block,AllocationPolicy(SizeOfBlock(block)));
00336   if (SizeOfBlock(block) > size)
00337     {
00338       size_t
00339         blocksize;
00340 
00341       void
00342         *next;
00343 
00344       /*
00345         Split block.
00346       */
00347       next=(char *) block+size;
00348       blocksize=SizeOfBlock(block)-size;
00349       *BlockHeader(next)=blocksize;
00350       *BlockFooter(next,blocksize)=blocksize;
00351       InsertFreeBlock(next,AllocationPolicy(blocksize));
00352       *BlockHeader(block)=size | (*BlockHeader(block) & ~SizeMask);
00353     }
00354   assert(size == SizeOfBlock(block));
00355   *BlockHeader(NextBlock(block))|=PreviousBlockBit;
00356   memory_info.allocation+=size;
00357   return(block);
00358 }
00359 #endif
00360 
00361 /*
00362 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00363 %                                                                             %
00364 %                                                                             %
00365 %                                                                             %
00366 %   A c q u i r e M a g i c k M e m o r y                                     %
00367 %                                                                             %
00368 %                                                                             %
00369 %                                                                             %
00370 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00371 %
00372 %  AcquireMagickMemory() returns a pointer to a block of memory at least size
00373 %  bytes suitably aligned for any use.
00374 %
00375 %  The format of the AcquireMagickMemory method is:
00376 %
00377 %      void *AcquireMagickMemory(const size_t size)
00378 %
00379 %  A description of each parameter follows:
00380 %
00381 %    o size: the size of the memory in bytes to allocate.
00382 %
00383 */
00384 MagickExport void *AcquireMagickMemory(const size_t size)
00385 {
00386   register void
00387     *memory;
00388 
00389 #if !defined(MAGICKCORE_EMBEDDABLE_SUPPORT)
00390   memory=memory_methods.acquire_memory_handler(size == 0 ? 1UL : size);
00391 #else
00392   if (memory_semaphore == (SemaphoreInfo *) NULL)
00393     AcquireSemaphoreInfo(&memory_semaphore);
00394   if (free_segments == (DataSegmentInfo *) NULL)
00395     {
00396       (void) LockSemaphoreInfo(memory_semaphore);
00397       if (free_segments == (DataSegmentInfo *) NULL)
00398         {
00399           register long
00400             i;
00401 
00402           assert(2*sizeof(size_t) > (size_t) (~SizeMask));
00403           (void) ResetMagickMemory(&memory_info,0,sizeof(memory_info));
00404           memory_info.allocation=SegmentSize;
00405           memory_info.blocks[MaxBlocks]=(void *) (-1);
00406           for (i=0; i < MaxSegments; i++)
00407           {
00408             if (i != 0)
00409               memory_info.segment_pool[i].previous=
00410                 (&memory_info.segment_pool[i-1]);
00411             if (i != (MaxSegments-1))
00412               memory_info.segment_pool[i].next=(&memory_info.segment_pool[i+1]);
00413           }
00414           free_segments=(&memory_info.segment_pool[0]);
00415         }
00416       (void) UnlockSemaphoreInfo(memory_semaphore);
00417     }
00418   (void) LockSemaphoreInfo(memory_semaphore);
00419   memory=AcquireBlock(size == 0 ? 1UL : size);
00420   if (memory == (void *) NULL)
00421     {
00422       if (ExpandHeap(size == 0 ? 1UL : size) != MagickFalse)
00423         memory=AcquireBlock(size == 0 ? 1UL : size);
00424     }
00425   (void) UnlockSemaphoreInfo(memory_semaphore);
00426 #endif
00427   return(memory);
00428 }
00429 
00430 /*
00431 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00432 %                                                                             %
00433 %                                                                             %
00434 %                                                                             %
00435 %   A c q u i r e Q u a n t u m M e m o r y                                   %
00436 %                                                                             %
00437 %                                                                             %
00438 %                                                                             %
00439 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00440 %
00441 %  AcquireQuantumMemory() returns a pointer to a block of memory at least
00442 %  count * quantum bytes suitably aligned for any use.
00443 %
00444 %  The format of the AcquireQuantumMemory method is:
00445 %
00446 %      void *AcquireQuantumMemory(const size_t count,const size_t quantum)
00447 %
00448 %  A description of each parameter follows:
00449 %
00450 %    o count: the number of quantum elements to allocate.
00451 %
00452 %    o quantum: the number of bytes in each quantum.
00453 %
00454 */
00455 MagickExport void *AcquireQuantumMemory(const size_t count,const size_t quantum)
00456 {
00457   size_t
00458     size;
00459 
00460   size=count*quantum;
00461   if ((count == 0) || (quantum != (size/count)))
00462     {
00463       errno=ENOMEM;
00464       return((void *) NULL);
00465     }
00466   return(AcquireMagickMemory(size));
00467 }
00468 
00469 /*
00470 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00471 %                                                                             %
00472 %                                                                             %
00473 %                                                                             %
00474 %   C o p y M a g i c k M e m o r y                                           %
00475 %                                                                             %
00476 %                                                                             %
00477 %                                                                             %
00478 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00479 %
00480 %  CopyMagickMemory() copies size bytes from memory area source to the
00481 %  destination.  Copying between objects that overlap will take place
00482 %  correctly.  It returns destination.
00483 %
00484 %  The format of the CopyMagickMemory method is:
00485 %
00486 %      void *CopyMagickMemory(void *destination,const void *source,
00487 %        const size_t size)
00488 %
00489 %  A description of each parameter follows:
00490 %
00491 %    o destination: the destination.
00492 %
00493 %    o source: the source.
00494 %
00495 %    o size: the size of the memory in bytes to allocate.
00496 %
00497 */
00498 MagickExport void *CopyMagickMemory(void *destination,const void *source,
00499   const size_t size)
00500 {
00501   register const unsigned char
00502     *p;
00503 
00504   register unsigned char
00505     *q;
00506 
00507   assert(destination != (void *) NULL);
00508   assert(source != (const void *) NULL);
00509   p=(const unsigned char *) source;
00510   q=(unsigned char *) destination;
00511   if (((q+size) < p) || (q > (p+size)))
00512     switch (size)
00513     {
00514       default: return(memcpy(destination,source,size));
00515       case 7: *q++=(*p++);
00516       case 6: *q++=(*p++);
00517       case 5: *q++=(*p++);
00518       case 4: *q++=(*p++);
00519       case 3: *q++=(*p++);
00520       case 2: *q++=(*p++);
00521       case 1: *q++=(*p++);
00522       case 0: return(destination);
00523     }
00524   return(memmove(destination,source,size));
00525 }
00526 
00527 /*
00528 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00529 %                                                                             %
00530 %                                                                             %
00531 %                                                                             %
00532 +   D e s t r o y M a g i c k M e m o r y                                     %
00533 %                                                                             %
00534 %                                                                             %
00535 %                                                                             %
00536 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00537 %
00538 %  DestroyMagickMemory() deallocates memory associated with the memory manager.
00539 %
00540 %  The format of the DestroyMagickMemory method is:
00541 %
00542 %      DestroyMagickMemory(void)
00543 %
00544 */
00545 MagickExport void DestroyMagickMemory(void)
00546 {
00547 #if defined(MAGICKCORE_EMBEDDABLE_SUPPORT)
00548   register long
00549     i;
00550 
00551   if (memory_semaphore == (SemaphoreInfo *) NULL)
00552     AcquireSemaphoreInfo(&memory_semaphore);
00553   (void) LockSemaphoreInfo(memory_semaphore);
00554   (void) UnlockSemaphoreInfo(memory_semaphore);
00555   for (i=0; i < (long) memory_info.number_segments; i++)
00556     if (memory_info.segments[i]->mapped == MagickFalse)
00557       memory_methods.destroy_memory_handler(
00558         memory_info.segments[i]->allocation);
00559     else
00560       (void) UnmapBlob(memory_info.segments[i]->allocation,
00561         memory_info.segments[i]->length);
00562   free_segments=(DataSegmentInfo *) NULL;
00563   (void) ResetMagickMemory(&memory_info,0,sizeof(memory_info));
00564   DestroySemaphoreInfo(&memory_semaphore);
00565 #endif
00566 }
00567 
00568 #if defined(MAGICKCORE_EMBEDDABLE_SUPPORT)
00569 /*
00570 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00571 %                                                                             %
00572 %                                                                             %
00573 %                                                                             %
00574 +   E x p a n d H e a p                                                       %
00575 %                                                                             %
00576 %                                                                             %
00577 %                                                                             %
00578 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00579 %
00580 %  ExpandHeap() get more memory from the system.  It returns MagickTrue on
00581 %  success otherwise MagickFalse.
00582 %
00583 %  The format of the ExpandHeap method is:
00584 %
00585 %      MagickBooleanType ExpandHeap(size_t size)
00586 %
00587 %  A description of each parameter follows:
00588 %
00589 %    o size: the size of the memory in bytes we require.
00590 %
00591 */
00592 static MagickBooleanType ExpandHeap(size_t size)
00593 {
00594   DataSegmentInfo
00595     *segment_info;
00596 
00597   MagickBooleanType
00598     mapped;
00599 
00600   register long
00601     i;
00602 
00603   register void
00604     *block;
00605 
00606   size_t
00607     blocksize;
00608 
00609   void
00610     *segment;
00611 
00612   blocksize=((size+12*sizeof(size_t))+SegmentSize-1) & -SegmentSize;
00613   assert(memory_info.number_segments < MaxSegments);
00614   segment=MapBlob(-1,IOMode,0,blocksize);
00615   mapped=segment != (void *) NULL ? MagickTrue : MagickFalse;
00616   if (segment == (void *) NULL)
00617     segment=(void *) memory_methods.acquire_memory_handler(blocksize);
00618   if (segment == (void *) NULL)
00619     return(MagickFalse);
00620   segment_info=(DataSegmentInfo *) free_segments;
00621   free_segments=segment_info->next;
00622   segment_info->mapped=mapped;
00623   segment_info->length=blocksize;
00624   segment_info->allocation=segment;
00625   segment_info->bound=(char *) segment+blocksize;
00626   i=(long) memory_info.number_segments-1;
00627   for ( ; (i >= 0) && (memory_info.segments[i]->allocation > segment); i--)
00628     memory_info.segments[i+1]=memory_info.segments[i];
00629   memory_info.segments[i+1]=segment_info;
00630   memory_info.number_segments++;
00631   size=blocksize-12*sizeof(size_t);
00632   block=(char *) segment_info->allocation+4*sizeof(size_t);
00633   *BlockHeader(block)=size | PreviousBlockBit;
00634   *BlockFooter(block,size)=size;
00635   InsertFreeBlock(block,AllocationPolicy(size));
00636   block=NextBlock(block);
00637   assert(block < segment_info->bound);
00638   *BlockHeader(block)=2*sizeof(size_t);
00639   *BlockHeader(NextBlock(block))=PreviousBlockBit;
00640   return(MagickTrue);
00641 }
00642 #endif
00643 
00644 /*
00645 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00646 %                                                                             %
00647 %                                                                             %
00648 %                                                                             %
00649 %   G e t M a g i c k M e m o r y M e t h o d s                               %
00650 %                                                                             %
00651 %                                                                             %
00652 %                                                                             %
00653 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00654 %
00655 %  GetMagickMemoryMethods() gets the methods to acquire, resize, and destroy
00656 %  memory.
00657 %
00658 %  The format of the GetMagickMemoryMethods() method is:
00659 %
00660 %      void GetMagickMemoryMethods(AcquireMemoryHandler *acquire_memory_handler,
00661 %        ResizeMemoryHandler *resize_memory_handler,
00662 %        DestroyMemoryHandler *destroy_memory_handler)
00663 %
00664 %  A description of each parameter follows:
00665 %
00666 %    o acquire_memory_handler: method to acquire memory (e.g. malloc).
00667 %
00668 %    o resize_memory_handler: method to resize memory (e.g. realloc).
00669 %
00670 %    o destroy_memory_handler: method to destroy memory (e.g. free).
00671 %
00672 */
00673 MagickExport void GetMagickMemoryMethods(
00674   AcquireMemoryHandler *acquire_memory_handler,
00675   ResizeMemoryHandler *resize_memory_handler,
00676   DestroyMemoryHandler *destroy_memory_handler)
00677 {
00678   assert(acquire_memory_handler != (AcquireMemoryHandler *) NULL);
00679   assert(resize_memory_handler != (ResizeMemoryHandler *) NULL);
00680   assert(destroy_memory_handler != (DestroyMemoryHandler *) NULL);
00681   *acquire_memory_handler=memory_methods.acquire_memory_handler;
00682   *resize_memory_handler=memory_methods.resize_memory_handler;
00683   *destroy_memory_handler=memory_methods.destroy_memory_handler;
00684 }
00685 
00686 /*
00687 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00688 %                                                                             %
00689 %                                                                             %
00690 %                                                                             %
00691 %   R e l i n q u i s h A l i g n e d M e m o r y                             %
00692 %                                                                             %
00693 %                                                                             %
00694 %                                                                             %
00695 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00696 %
00697 %  RelinquishAlignedMemory() frees memory acquired with AcquireAlignedMemory()
00698 %  or reuse.
00699 %
00700 %  The format of the RelinquishAlignedMemory method is:
00701 %
00702 %      void *RelinquishAlignedMemory(void *memory)
00703 %
00704 %  A description of each parameter follows:
00705 %
00706 %    o memory: A pointer to a block of memory to free for reuse.
00707 %
00708 */
00709 MagickExport void *RelinquishAlignedMemory(void *memory)
00710 {
00711   if (memory == (void *) NULL)
00712     return((void *) NULL);
00713   free(memory);
00714   return((void *) NULL);
00715 }
00716 
00717 /*
00718 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00719 %                                                                             %
00720 %                                                                             %
00721 %                                                                             %
00722 %   R e l i n q u i s h M a g i c k M e m o r y                               %
00723 %                                                                             %
00724 %                                                                             %
00725 %                                                                             %
00726 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00727 %
00728 %  RelinquishMagickMemory() frees memory acquired with AcquireMagickMemory()
00729 %  or AcquireQuantumMemory() for reuse.
00730 %
00731 %  The format of the RelinquishMagickMemory method is:
00732 %
00733 %      void *RelinquishMagickMemory(void *memory)
00734 %
00735 %  A description of each parameter follows:
00736 %
00737 %    o memory: A pointer to a block of memory to free for reuse.
00738 %
00739 */
00740 MagickExport void *RelinquishMagickMemory(void *memory)
00741 {
00742   if (memory == (void *) NULL)
00743     return((void *) NULL);
00744 #if !defined(MAGICKCORE_EMBEDDABLE_SUPPORT)
00745   memory_methods.destroy_memory_handler(memory);
00746 #else
00747   assert((SizeOfBlock(memory) % (4*sizeof(size_t))) == 0);
00748   assert((*BlockHeader(NextBlock(memory)) & PreviousBlockBit) != 0);
00749   (void) LockSemaphoreInfo(memory_semaphore);
00750   if ((*BlockHeader(memory) & PreviousBlockBit) == 0)
00751     {
00752       void
00753         *previous;
00754 
00755       /*
00756         Coalesce with previous adjacent block.
00757       */
00758       previous=PreviousBlock(memory);
00759       RemoveFreeBlock(previous,AllocationPolicy(SizeOfBlock(previous)));
00760       *BlockHeader(previous)=(SizeOfBlock(previous)+SizeOfBlock(memory)) |
00761         (*BlockHeader(previous) & ~SizeMask);
00762       memory=previous;
00763     }
00764   if ((*BlockHeader(NextBlock(NextBlock(memory))) & PreviousBlockBit) == 0)
00765     {
00766       void
00767         *next;
00768 
00769       /*
00770         Coalesce with next adjacent block.
00771       */
00772       next=NextBlock(memory);
00773       RemoveFreeBlock(next,AllocationPolicy(SizeOfBlock(next)));
00774       *BlockHeader(memory)=(SizeOfBlock(memory)+SizeOfBlock(next)) |
00775         (*BlockHeader(memory) & ~SizeMask);
00776     }
00777   *BlockFooter(memory,SizeOfBlock(memory))=SizeOfBlock(memory);
00778   *BlockHeader(NextBlock(memory))&=(~PreviousBlockBit);
00779   InsertFreeBlock(memory,AllocationPolicy(SizeOfBlock(memory)));
00780   (void) UnlockSemaphoreInfo(memory_semaphore);
00781 #endif
00782   return((void *) NULL);
00783 }
00784 
00785 /*
00786 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00787 %                                                                             %
00788 %                                                                             %
00789 %                                                                             %
00790 %   R e s e t M a g i c k M e m o r y                                         %
00791 %                                                                             %
00792 %                                                                             %
00793 %                                                                             %
00794 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00795 %
00796 %  ResetMagickMemory() fills the first size bytes of the memory area pointed to
00797 %  by memory with the constant byte c.
00798 %
00799 %  The format of the ResetMagickMemory method is:
00800 %
00801 %      void *ResetMagickMemory(void *memory,int byte,const size_t size)
00802 %
00803 %  A description of each parameter follows:
00804 %
00805 %    o memory: A pointer to a memory allocation.
00806 %
00807 %    o byte: Set the memory to this value.
00808 %
00809 %    o size: Size of the memory to reset.
00810 %
00811 */
00812 MagickExport void *ResetMagickMemory(void *memory,int byte,const size_t size)
00813 {
00814   assert(memory != (void *) NULL);
00815   return(memset(memory,byte,size));
00816 }
00817 
00818 /*
00819 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00820 %                                                                             %
00821 %                                                                             %
00822 %                                                                             %
00823 %   R e s i z e M a g i c k M e m o r y                                       %
00824 %                                                                             %
00825 %                                                                             %
00826 %                                                                             %
00827 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00828 %
00829 %  ResizeMagickMemory() changes the size of the memory and returns a pointer to
00830 %  the (possibly moved) block.  The contents will be unchanged up to the
00831 %  lesser of the new and old sizes.
00832 %
00833 %  The format of the ResizeMagickMemory method is:
00834 %
00835 %      void *ResizeMagickMemory(void *memory,const size_t size)
00836 %
00837 %  A description of each parameter follows:
00838 %
00839 %    o memory: A pointer to a memory allocation.
00840 %
00841 %    o size: the new size of the allocated memory.
00842 %
00843 */
00844 
00845 #if defined(MAGICKCORE_EMBEDDABLE_SUPPORT)
00846 static inline void *ResizeBlock(void *block,size_t size)
00847 {
00848   register void
00849     *memory;
00850 
00851   if (block == (void *) NULL)
00852     return(AcquireBlock(size));
00853   memory=AcquireBlock(size);
00854   if (memory == (void *) NULL)
00855     return((void *) NULL);
00856   if (size <= (SizeOfBlock(block)-sizeof(size_t)))
00857     (void) memcpy(memory,block,size);
00858   else
00859     (void) memcpy(memory,block,SizeOfBlock(block)-sizeof(size_t));
00860   memory_info.allocation+=size;
00861   return(memory);
00862 }
00863 #endif
00864 
00865 MagickExport void *ResizeMagickMemory(void *memory,const size_t size)
00866 {
00867   register void
00868     *block;
00869 
00870   if (memory == (void *) NULL)
00871     return(AcquireMagickMemory(size));
00872 #if !defined(MAGICKCORE_EMBEDDABLE_SUPPORT)
00873   block=memory_methods.resize_memory_handler(memory,size == 0 ? 1UL : size);
00874   if (block == (void *) NULL)
00875     memory=RelinquishMagickMemory(memory);
00876 #else
00877   (void) LockSemaphoreInfo(memory_semaphore);
00878   block=ResizeBlock(memory,size == 0 ? 1UL : size);
00879   if (block == (void *) NULL)
00880     {
00881       if (ExpandHeap(size == 0 ? 1UL : size) == MagickFalse)
00882         {
00883           (void) UnlockSemaphoreInfo(memory_semaphore);
00884           memory=RelinquishMagickMemory(memory);
00885           ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00886         }
00887       block=ResizeBlock(memory,size == 0 ? 1UL : size);
00888       assert(block != (void *) NULL);
00889     }
00890   (void) UnlockSemaphoreInfo(memory_semaphore);
00891   memory=RelinquishMagickMemory(memory);
00892 #endif
00893   return(block);
00894 }
00895 
00896 /*
00897 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00898 %                                                                             %
00899 %                                                                             %
00900 %                                                                             %
00901 %   R e s i z e Q u a n t u m M e m o r y                                     %
00902 %                                                                             %
00903 %                                                                             %
00904 %                                                                             %
00905 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00906 %
00907 %  ResizeQuantumMemory() changes the size of the memory and returns a pointer
00908 %  to the (possibly moved) block.  The contents will be unchanged up to the
00909 %  lesser of the new and old sizes.
00910 %
00911 %  The format of the ResizeQuantumMemory method is:
00912 %
00913 %      void *ResizeQuantumMemory(void *memory,const size_t count,
00914 %        const size_t quantum)
00915 %
00916 %  A description of each parameter follows:
00917 %
00918 %    o memory: A pointer to a memory allocation.
00919 %
00920 %    o count: the number of quantum elements to allocate.
00921 %
00922 %    o quantum: the number of bytes in each quantum.
00923 %
00924 */
00925 MagickExport void *ResizeQuantumMemory(void *memory,const size_t count,
00926   const size_t quantum)
00927 {
00928   size_t
00929     size;
00930 
00931   size=count*quantum;
00932   if ((count == 0) || (quantum != (size/count)))
00933     {
00934       memory=RelinquishMagickMemory(memory);
00935       errno=ENOMEM;
00936       return((void *) NULL);
00937     }
00938   return(ResizeMagickMemory(memory,size));
00939 }
00940 
00941 /*
00942 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00943 %                                                                             %
00944 %                                                                             %
00945 %                                                                             %
00946 %   S e t M a g i c k M e m o r y M e t h o d s                               %
00947 %                                                                             %
00948 %                                                                             %
00949 %                                                                             %
00950 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00951 %
00952 %  SetMagickMemoryMethods() sets the methods to acquire, resize, and destroy
00953 %  memory.
00954 %
00955 %  The format of the SetMagickMemoryMethods() method is:
00956 %
00957 %      SetMagickMemoryMethods(AcquireMemoryHandler acquire_memory_handler,
00958 %        ResizeMemoryHandler resize_memory_handler,
00959 %        DestroyMemoryHandler destroy_memory_handler)
00960 %
00961 %  A description of each parameter follows:
00962 %
00963 %    o acquire_memory_handler: method to acquire memory (e.g. malloc).
00964 %
00965 %    o resize_memory_handler: method to resize memory (e.g. realloc).
00966 %
00967 %    o destroy_memory_handler: method to destroy memory (e.g. free).
00968 %
00969 */
00970 MagickExport void SetMagickMemoryMethods(
00971   AcquireMemoryHandler acquire_memory_handler,
00972   ResizeMemoryHandler resize_memory_handler,
00973   DestroyMemoryHandler destroy_memory_handler)
00974 {
00975   /*
00976     Set memory methods.
00977   */
00978   if (acquire_memory_handler != (AcquireMemoryHandler) NULL)
00979     memory_methods.acquire_memory_handler=acquire_memory_handler;
00980   if (resize_memory_handler != (ResizeMemoryHandler) NULL)
00981     memory_methods.resize_memory_handler=resize_memory_handler;
00982   if (destroy_memory_handler != (DestroyMemoryHandler) NULL)
00983     memory_methods.destroy_memory_handler=destroy_memory_handler;
00984 }

Generated on 19 Nov 2009 for MagickCore by  doxygen 1.6.1