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

Generated on Thu Jul 2 12:03:20 2009 for MagickCore by  doxygen 1.5.8