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