]> granicus.if.org Git - imagemagick/blob - MagickCore/memory.c
(no commit message)
[imagemagick] / MagickCore / 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-2012 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_ZERO_CONFIGURATION_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 "MagickCore/studio.h"
57 #include "MagickCore/blob.h"
58 #include "MagickCore/blob-private.h"
59 #include "MagickCore/exception.h"
60 #include "MagickCore/exception-private.h"
61 #include "MagickCore/memory_.h"
62 #include "MagickCore/memory-private.h"
63 #include "MagickCore/semaphore.h"
64 #include "MagickCore/string_.h"
65 \f
66 /*
67   Define declarations.
68 */
69 #define BlockFooter(block,size) \
70   ((size_t *) ((char *) (block)+(size)-2*sizeof(size_t)))
71 #define BlockHeader(block)  ((size_t *) (block)-1)
72 #define BlockSize  4096
73 #define BlockThreshold  1024
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_ZERO_CONFIGURATION_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 MagickExport void *AcquireAlignedMemory(const size_t count,const size_t quantum)
190 {
191   size_t
192     size;
193
194   size=count*quantum;
195   if ((count == 0) || (quantum != (size/count)))
196     {
197       errno=ENOMEM;
198       return((void *) NULL);
199     }
200 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
201   {
202     void
203       *memory;
204
205     if (posix_memalign(&memory,CACHE_LINE_SIZE,CacheAlign(size)) == 0)
206       return(memory);
207   }
208 #endif
209   return(malloc(CacheAlign(size)));
210 }
211 \f
212 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
213 /*
214 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
215 %                                                                             %
216 %                                                                             %
217 %                                                                             %
218 +   A c q u i r e B l o c k                                                   %
219 %                                                                             %
220 %                                                                             %
221 %                                                                             %
222 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
223 %
224 %  AcquireBlock() returns a pointer to a block of memory at least size bytes
225 %  suitably aligned for any use.
226 %
227 %  The format of the AcquireBlock method is:
228 %
229 %      void *AcquireBlock(const size_t size)
230 %
231 %  A description of each parameter follows:
232 %
233 %    o size: the size of the memory in bytes to allocate.
234 %
235 */
236
237 static inline size_t AllocationPolicy(size_t size)
238 {
239   register size_t
240     blocksize;
241
242   /*
243     The linear distribution.
244   */
245   assert(size != 0);
246   assert(size % (4*sizeof(size_t)) == 0);
247   if (size <= BlockThreshold)
248     return(size/(4*sizeof(size_t)));
249   /*
250     Check for the largest block size.
251   */
252   if (size > (size_t) (BlockThreshold*(1L << (MaxBlockExponent-1L))))
253     return(MaxBlocks-1L);
254   /*
255     Otherwise use a power of two distribution.
256   */
257   blocksize=BlockThreshold/(4*sizeof(size_t));
258   for ( ; size > BlockThreshold; size/=2)
259     blocksize++;
260   assert(blocksize > (BlockThreshold/(4*sizeof(size_t))));
261   assert(blocksize < (MaxBlocks-1L));
262   return(blocksize);
263 }
264
265 static inline void InsertFreeBlock(void *block,const size_t i)
266 {
267   register void
268     *next,
269     *previous;
270
271   size_t
272     size;
273
274   size=SizeOfBlock(block);
275   previous=(void *) NULL;
276   next=memory_info.blocks[i];
277   while ((next != (void *) NULL) && (SizeOfBlock(next) < size))
278   {
279     previous=next;
280     next=NextBlockInList(next);
281   }
282   PreviousBlockInList(block)=previous;
283   NextBlockInList(block)=next;
284   if (previous != (void *) NULL)
285     NextBlockInList(previous)=block;
286   else
287     memory_info.blocks[i]=block;
288   if (next != (void *) NULL)
289     PreviousBlockInList(next)=block;
290 }
291
292 static inline void RemoveFreeBlock(void *block,const size_t i)
293 {
294   register void
295     *next,
296     *previous;
297
298   next=NextBlockInList(block);
299   previous=PreviousBlockInList(block);
300   if (previous == (void *) NULL)
301     memory_info.blocks[i]=next;
302   else
303     NextBlockInList(previous)=next;
304   if (next != (void *) NULL)
305     PreviousBlockInList(next)=previous;
306 }
307
308 static void *AcquireBlock(size_t size)
309 {
310   register size_t
311     i;
312
313   register void
314     *block;
315
316   /*
317     Find free block.
318   */
319   size=(size_t) (size+sizeof(size_t)+6*sizeof(size_t)-1) & -(4U*sizeof(size_t));
320   i=AllocationPolicy(size);
321   block=memory_info.blocks[i];
322   while ((block != (void *) NULL) && (SizeOfBlock(block) < size))
323     block=NextBlockInList(block);
324   if (block == (void *) NULL)
325     {
326       i++;
327       while (memory_info.blocks[i] == (void *) NULL)
328         i++;
329       block=memory_info.blocks[i];
330       if (i >= MaxBlocks)
331         return((void *) NULL);
332     }
333   assert((*BlockHeader(NextBlock(block)) & PreviousBlockBit) == 0);
334   assert(SizeOfBlock(block) >= size);
335   RemoveFreeBlock(block,AllocationPolicy(SizeOfBlock(block)));
336   if (SizeOfBlock(block) > size)
337     {
338       size_t
339         blocksize;
340
341       void
342         *next;
343
344       /*
345         Split block.
346       */
347       next=(char *) block+size;
348       blocksize=SizeOfBlock(block)-size;
349       *BlockHeader(next)=blocksize;
350       *BlockFooter(next,blocksize)=blocksize;
351       InsertFreeBlock(next,AllocationPolicy(blocksize));
352       *BlockHeader(block)=size | (*BlockHeader(block) & ~SizeMask);
353     }
354   assert(size == SizeOfBlock(block));
355   *BlockHeader(NextBlock(block))|=PreviousBlockBit;
356   memory_info.allocation+=size;
357   return(block);
358 }
359 #endif
360 \f
361 /*
362 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
363 %                                                                             %
364 %                                                                             %
365 %                                                                             %
366 %   A c q u i r e M a g i c k M e m o r y                                     %
367 %                                                                             %
368 %                                                                             %
369 %                                                                             %
370 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
371 %
372 %  AcquireMagickMemory() returns a pointer to a block of memory at least size
373 %  bytes suitably aligned for any use.
374 %
375 %  The format of the AcquireMagickMemory method is:
376 %
377 %      void *AcquireMagickMemory(const size_t size)
378 %
379 %  A description of each parameter follows:
380 %
381 %    o size: the size of the memory in bytes to allocate.
382 %
383 */
384 MagickExport void *AcquireMagickMemory(const size_t size)
385 {
386   register void
387     *memory;
388
389 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
390   memory=memory_methods.acquire_memory_handler(size == 0 ? 1UL : size);
391 #else
392   if (memory_semaphore == (SemaphoreInfo *) NULL)
393     AcquireSemaphoreInfo(&memory_semaphore);
394   if (free_segments == (DataSegmentInfo *) NULL)
395     {
396       LockSemaphoreInfo(memory_semaphore);
397       if (free_segments == (DataSegmentInfo *) NULL)
398         {
399           register ssize_t
400             i;
401
402           assert(2*sizeof(size_t) > (size_t) (~SizeMask));
403           (void) ResetMagickMemory(&memory_info,0,sizeof(memory_info));
404           memory_info.allocation=SegmentSize;
405           memory_info.blocks[MaxBlocks]=(void *) (-1);
406           for (i=0; i < MaxSegments; i++)
407           {
408             if (i != 0)
409               memory_info.segment_pool[i].previous=
410                 (&memory_info.segment_pool[i-1]);
411             if (i != (MaxSegments-1))
412               memory_info.segment_pool[i].next=(&memory_info.segment_pool[i+1]);
413           }
414           free_segments=(&memory_info.segment_pool[0]);
415         }
416       UnlockSemaphoreInfo(memory_semaphore);
417     }
418   LockSemaphoreInfo(memory_semaphore);
419   memory=AcquireBlock(size == 0 ? 1UL : size);
420   if (memory == (void *) NULL)
421     {
422       if (ExpandHeap(size == 0 ? 1UL : size) != MagickFalse)
423         memory=AcquireBlock(size == 0 ? 1UL : size);
424     }
425   UnlockSemaphoreInfo(memory_semaphore);
426 #endif
427   return(memory);
428 }
429 \f
430 /*
431 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
432 %                                                                             %
433 %                                                                             %
434 %                                                                             %
435 %   A c q u i r e Q u a n t u m M e m o r y                                   %
436 %                                                                             %
437 %                                                                             %
438 %                                                                             %
439 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
440 %
441 %  AcquireQuantumMemory() returns a pointer to a block of memory at least
442 %  count * quantum bytes suitably aligned for any use.
443 %
444 %  The format of the AcquireQuantumMemory method is:
445 %
446 %      void *AcquireQuantumMemory(const size_t count,const size_t quantum)
447 %
448 %  A description of each parameter follows:
449 %
450 %    o count: the number of quantum elements to allocate.
451 %
452 %    o quantum: the number of bytes in each quantum.
453 %
454 */
455 MagickExport void *AcquireQuantumMemory(const size_t count,const size_t quantum)
456 {
457   size_t
458     size;
459
460   size=count*quantum;
461   if ((count == 0) || (quantum != (size/count)))
462     {
463       errno=ENOMEM;
464       return((void *) NULL);
465     }
466   return(AcquireMagickMemory(size));
467 }
468 \f
469 /*
470 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
471 %                                                                             %
472 %                                                                             %
473 %                                                                             %
474 %   C o p y M a g i c k M e m o r y                                           %
475 %                                                                             %
476 %                                                                             %
477 %                                                                             %
478 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
479 %
480 %  CopyMagickMemory() copies size bytes from memory area source to the
481 %  destination.  Copying between objects that overlap will take place
482 %  correctly.  It returns destination.
483 %
484 %  The format of the CopyMagickMemory method is:
485 %
486 %      void *CopyMagickMemory(void *destination,const void *source,
487 %        const size_t size)
488 %
489 %  A description of each parameter follows:
490 %
491 %    o destination: the destination.
492 %
493 %    o source: the source.
494 %
495 %    o size: the size of the memory in bytes to allocate.
496 %
497 */
498 MagickExport void *CopyMagickMemory(void *destination,const void *source,
499   const size_t size)
500 {
501   register const unsigned char
502     *p;
503
504   register unsigned char
505     *q;
506
507   assert(destination != (void *) NULL);
508   assert(source != (const void *) NULL);
509   p=(const unsigned char *) source;
510   q=(unsigned char *) destination;
511   if (((q+size) < p) || (q > (p+size)))
512     switch (size)
513     {
514       default: return(memcpy(destination,source,size));
515       case 8: *q++=(*p++);
516       case 7: *q++=(*p++);
517       case 6: *q++=(*p++);
518       case 5: *q++=(*p++);
519       case 4: *q++=(*p++);
520       case 3: *q++=(*p++);
521       case 2: *q++=(*p++);
522       case 1: *q++=(*p++);
523       case 0: return(destination);
524     }
525   return(memmove(destination,source,size));
526 }
527 \f
528 /*
529 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
530 %                                                                             %
531 %                                                                             %
532 %                                                                             %
533 +   D e s t r o y M a g i c k M e m o r y                                     %
534 %                                                                             %
535 %                                                                             %
536 %                                                                             %
537 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
538 %
539 %  DestroyMagickMemory() deallocates memory associated with the memory manager.
540 %
541 %  The format of the DestroyMagickMemory method is:
542 %
543 %      DestroyMagickMemory(void)
544 %
545 */
546 MagickExport void DestroyMagickMemory(void)
547 {
548 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
549   register ssize_t
550     i;
551
552   if (memory_semaphore == (SemaphoreInfo *) NULL)
553     AcquireSemaphoreInfo(&memory_semaphore);
554   LockSemaphoreInfo(memory_semaphore);
555   UnlockSemaphoreInfo(memory_semaphore);
556   for (i=0; i < (ssize_t) memory_info.number_segments; i++)
557     if (memory_info.segments[i]->mapped == MagickFalse)
558       memory_methods.destroy_memory_handler(
559         memory_info.segments[i]->allocation);
560     else
561       (void) UnmapBlob(memory_info.segments[i]->allocation,
562         memory_info.segments[i]->length);
563   free_segments=(DataSegmentInfo *) NULL;
564   (void) ResetMagickMemory(&memory_info,0,sizeof(memory_info));
565   DestroySemaphoreInfo(&memory_semaphore);
566 #endif
567 }
568 \f
569 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
570 /*
571 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
572 %                                                                             %
573 %                                                                             %
574 %                                                                             %
575 +   E x p a n d H e a p                                                       %
576 %                                                                             %
577 %                                                                             %
578 %                                                                             %
579 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
580 %
581 %  ExpandHeap() get more memory from the system.  It returns MagickTrue on
582 %  success otherwise MagickFalse.
583 %
584 %  The format of the ExpandHeap method is:
585 %
586 %      MagickBooleanType ExpandHeap(size_t size)
587 %
588 %  A description of each parameter follows:
589 %
590 %    o size: the size of the memory in bytes we require.
591 %
592 */
593 static MagickBooleanType ExpandHeap(size_t size)
594 {
595   DataSegmentInfo
596     *segment_info;
597
598   MagickBooleanType
599     mapped;
600
601   register ssize_t
602     i;
603
604   register void
605     *block;
606
607   size_t
608     blocksize;
609
610   void
611     *segment;
612
613   blocksize=((size+12*sizeof(size_t))+SegmentSize-1) & -SegmentSize;
614   assert(memory_info.number_segments < MaxSegments);
615   segment=MapBlob(-1,IOMode,0,blocksize);
616   mapped=segment != (void *) NULL ? MagickTrue : MagickFalse;
617   if (segment == (void *) NULL)
618     segment=(void *) memory_methods.acquire_memory_handler(blocksize);
619   if (segment == (void *) NULL)
620     return(MagickFalse);
621   segment_info=(DataSegmentInfo *) free_segments;
622   free_segments=segment_info->next;
623   segment_info->mapped=mapped;
624   segment_info->length=blocksize;
625   segment_info->allocation=segment;
626   segment_info->bound=(char *) segment+blocksize;
627   i=(ssize_t) memory_info.number_segments-1;
628   for ( ; (i >= 0) && (memory_info.segments[i]->allocation > segment); i--)
629     memory_info.segments[i+1]=memory_info.segments[i];
630   memory_info.segments[i+1]=segment_info;
631   memory_info.number_segments++;
632   size=blocksize-12*sizeof(size_t);
633   block=(char *) segment_info->allocation+4*sizeof(size_t);
634   *BlockHeader(block)=size | PreviousBlockBit;
635   *BlockFooter(block,size)=size;
636   InsertFreeBlock(block,AllocationPolicy(size));
637   block=NextBlock(block);
638   assert(block < segment_info->bound);
639   *BlockHeader(block)=2*sizeof(size_t);
640   *BlockHeader(NextBlock(block))=PreviousBlockBit;
641   return(MagickTrue);
642 }
643 #endif
644 \f
645 /*
646 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
647 %                                                                             %
648 %                                                                             %
649 %                                                                             %
650 %   G e t M a g i c k M e m o r y M e t h o d s                               %
651 %                                                                             %
652 %                                                                             %
653 %                                                                             %
654 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
655 %
656 %  GetMagickMemoryMethods() gets the methods to acquire, resize, and destroy
657 %  memory.
658 %
659 %  The format of the GetMagickMemoryMethods() method is:
660 %
661 %      void GetMagickMemoryMethods(AcquireMemoryHandler *acquire_memory_handler,
662 %        ResizeMemoryHandler *resize_memory_handler,
663 %        DestroyMemoryHandler *destroy_memory_handler)
664 %
665 %  A description of each parameter follows:
666 %
667 %    o acquire_memory_handler: method to acquire memory (e.g. malloc).
668 %
669 %    o resize_memory_handler: method to resize memory (e.g. realloc).
670 %
671 %    o destroy_memory_handler: method to destroy memory (e.g. free).
672 %
673 */
674 MagickExport void GetMagickMemoryMethods(
675   AcquireMemoryHandler *acquire_memory_handler,
676   ResizeMemoryHandler *resize_memory_handler,
677   DestroyMemoryHandler *destroy_memory_handler)
678 {
679   assert(acquire_memory_handler != (AcquireMemoryHandler *) NULL);
680   assert(resize_memory_handler != (ResizeMemoryHandler *) NULL);
681   assert(destroy_memory_handler != (DestroyMemoryHandler *) NULL);
682   *acquire_memory_handler=memory_methods.acquire_memory_handler;
683   *resize_memory_handler=memory_methods.resize_memory_handler;
684   *destroy_memory_handler=memory_methods.destroy_memory_handler;
685 }
686 \f
687 /*
688 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
689 %                                                                             %
690 %                                                                             %
691 %                                                                             %
692 %   R e l i n q u i s h A l i g n e d M e m o r y                             %
693 %                                                                             %
694 %                                                                             %
695 %                                                                             %
696 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
697 %
698 %  RelinquishAlignedMemory() frees memory acquired with AcquireAlignedMemory()
699 %  or reuse.
700 %
701 %  The format of the RelinquishAlignedMemory method is:
702 %
703 %      void *RelinquishAlignedMemory(void *memory)
704 %
705 %  A description of each parameter follows:
706 %
707 %    o memory: A pointer to a block of memory to free for reuse.
708 %
709 */
710 MagickExport void *RelinquishAlignedMemory(void *memory)
711 {
712   if (memory == (void *) NULL)
713     return((void *) NULL);
714   free(memory);
715   return((void *) NULL);
716 }
717 \f
718 /*
719 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
720 %                                                                             %
721 %                                                                             %
722 %                                                                             %
723 %   R e l i n q u i s h M a g i c k M e m o r y                               %
724 %                                                                             %
725 %                                                                             %
726 %                                                                             %
727 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
728 %
729 %  RelinquishMagickMemory() frees memory acquired with AcquireMagickMemory()
730 %  or AcquireQuantumMemory() for reuse.
731 %
732 %  The format of the RelinquishMagickMemory method is:
733 %
734 %      void *RelinquishMagickMemory(void *memory)
735 %
736 %  A description of each parameter follows:
737 %
738 %    o memory: A pointer to a block of memory to free for reuse.
739 %
740 */
741 MagickExport void *RelinquishMagickMemory(void *memory)
742 {
743   if (memory == (void *) NULL)
744     return((void *) NULL);
745 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
746   memory_methods.destroy_memory_handler(memory);
747 #else
748   LockSemaphoreInfo(memory_semaphore);
749   assert((SizeOfBlock(memory) % (4*sizeof(size_t))) == 0);
750   assert((*BlockHeader(NextBlock(memory)) & PreviousBlockBit) != 0);
751   if ((*BlockHeader(memory) & PreviousBlockBit) == 0)
752     {
753       void
754         *previous;
755
756       /*
757         Coalesce with previous adjacent block.
758       */
759       previous=PreviousBlock(memory);
760       RemoveFreeBlock(previous,AllocationPolicy(SizeOfBlock(previous)));
761       *BlockHeader(previous)=(SizeOfBlock(previous)+SizeOfBlock(memory)) |
762         (*BlockHeader(previous) & ~SizeMask);
763       memory=previous;
764     }
765   if ((*BlockHeader(NextBlock(NextBlock(memory))) & PreviousBlockBit) == 0)
766     {
767       void
768         *next;
769
770       /*
771         Coalesce with next adjacent block.
772       */
773       next=NextBlock(memory);
774       RemoveFreeBlock(next,AllocationPolicy(SizeOfBlock(next)));
775       *BlockHeader(memory)=(SizeOfBlock(memory)+SizeOfBlock(next)) |
776         (*BlockHeader(memory) & ~SizeMask);
777     }
778   *BlockFooter(memory,SizeOfBlock(memory))=SizeOfBlock(memory);
779   *BlockHeader(NextBlock(memory))&=(~PreviousBlockBit);
780   InsertFreeBlock(memory,AllocationPolicy(SizeOfBlock(memory)));
781   UnlockSemaphoreInfo(memory_semaphore);
782 #endif
783   return((void *) NULL);
784 }
785 \f
786 /*
787 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
788 %                                                                             %
789 %                                                                             %
790 %                                                                             %
791 %   R e s e t M a g i c k M e m o r y                                         %
792 %                                                                             %
793 %                                                                             %
794 %                                                                             %
795 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
796 %
797 %  ResetMagickMemory() fills the first size bytes of the memory area pointed to
798 %  by memory with the constant byte c.
799 %
800 %  The format of the ResetMagickMemory method is:
801 %
802 %      void *ResetMagickMemory(void *memory,int byte,const size_t size)
803 %
804 %  A description of each parameter follows:
805 %
806 %    o memory: A pointer to a memory allocation.
807 %
808 %    o byte: Set the memory to this value.
809 %
810 %    o size: Size of the memory to reset.
811 %
812 */
813 MagickExport void *ResetMagickMemory(void *memory,int byte,const size_t size)
814 {
815   assert(memory != (void *) NULL);
816   return(memset(memory,byte,size));
817 }
818 \f
819 /*
820 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
821 %                                                                             %
822 %                                                                             %
823 %                                                                             %
824 %   R e s i z e M a g i c k M e m o r y                                       %
825 %                                                                             %
826 %                                                                             %
827 %                                                                             %
828 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
829 %
830 %  ResizeMagickMemory() changes the size of the memory and returns a pointer to
831 %  the (possibly moved) block.  The contents will be unchanged up to the
832 %  lesser of the new and old sizes.
833 %
834 %  The format of the ResizeMagickMemory method is:
835 %
836 %      void *ResizeMagickMemory(void *memory,const size_t size)
837 %
838 %  A description of each parameter follows:
839 %
840 %    o memory: A pointer to a memory allocation.
841 %
842 %    o size: the new size of the allocated memory.
843 %
844 */
845
846 #if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
847 static inline void *ResizeBlock(void *block,size_t size)
848 {
849   register void
850     *memory;
851
852   if (block == (void *) NULL)
853     return(AcquireBlock(size));
854   memory=AcquireBlock(size);
855   if (memory == (void *) NULL)
856     return((void *) NULL);
857   if (size <= (SizeOfBlock(block)-sizeof(size_t)))
858     (void) memcpy(memory,block,size);
859   else
860     (void) memcpy(memory,block,SizeOfBlock(block)-sizeof(size_t));
861   memory_info.allocation+=size;
862   return(memory);
863 }
864 #endif
865
866 MagickExport void *ResizeMagickMemory(void *memory,const size_t size)
867 {
868   register void
869     *block;
870
871   if (memory == (void *) NULL)
872     return(AcquireMagickMemory(size));
873 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
874   block=memory_methods.resize_memory_handler(memory,size == 0 ? 1UL : size);
875   if (block == (void *) NULL)
876     memory=RelinquishMagickMemory(memory);
877 #else
878   LockSemaphoreInfo(memory_semaphore);
879   block=ResizeBlock(memory,size == 0 ? 1UL : size);
880   if (block == (void *) NULL)
881     {
882       if (ExpandHeap(size == 0 ? 1UL : size) == MagickFalse)
883         {
884           UnlockSemaphoreInfo(memory_semaphore);
885           memory=RelinquishMagickMemory(memory);
886           ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
887         }
888       block=ResizeBlock(memory,size == 0 ? 1UL : size);
889       assert(block != (void *) NULL);
890     }
891   UnlockSemaphoreInfo(memory_semaphore);
892   memory=RelinquishMagickMemory(memory);
893 #endif
894   return(block);
895 }
896 \f
897 /*
898 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
899 %                                                                             %
900 %                                                                             %
901 %                                                                             %
902 %   R e s i z e Q u a n t u m M e m o r y                                     %
903 %                                                                             %
904 %                                                                             %
905 %                                                                             %
906 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
907 %
908 %  ResizeQuantumMemory() changes the size of the memory and returns a pointer
909 %  to the (possibly moved) block.  The contents will be unchanged up to the
910 %  lesser of the new and old sizes.
911 %
912 %  The format of the ResizeQuantumMemory method is:
913 %
914 %      void *ResizeQuantumMemory(void *memory,const size_t count,
915 %        const size_t quantum)
916 %
917 %  A description of each parameter follows:
918 %
919 %    o memory: A pointer to a memory allocation.
920 %
921 %    o count: the number of quantum elements to allocate.
922 %
923 %    o quantum: the number of bytes in each quantum.
924 %
925 */
926 MagickExport void *ResizeQuantumMemory(void *memory,const size_t count,
927   const size_t quantum)
928 {
929   size_t
930     size;
931
932   size=count*quantum;
933   if ((count == 0) || (quantum != (size/count)))
934     {
935       memory=RelinquishMagickMemory(memory);
936       errno=ENOMEM;
937       return((void *) NULL);
938     }
939   return(ResizeMagickMemory(memory,size));
940 }
941 \f
942 /*
943 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
944 %                                                                             %
945 %                                                                             %
946 %                                                                             %
947 %   S e t M a g i c k M e m o r y M e t h o d s                               %
948 %                                                                             %
949 %                                                                             %
950 %                                                                             %
951 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
952 %
953 %  SetMagickMemoryMethods() sets the methods to acquire, resize, and destroy
954 %  memory.
955 %
956 %  The format of the SetMagickMemoryMethods() method is:
957 %
958 %      SetMagickMemoryMethods(AcquireMemoryHandler acquire_memory_handler,
959 %        ResizeMemoryHandler resize_memory_handler,
960 %        DestroyMemoryHandler destroy_memory_handler)
961 %
962 %  A description of each parameter follows:
963 %
964 %    o acquire_memory_handler: method to acquire memory (e.g. malloc).
965 %
966 %    o resize_memory_handler: method to resize memory (e.g. realloc).
967 %
968 %    o destroy_memory_handler: method to destroy memory (e.g. free).
969 %
970 */
971 MagickExport void SetMagickMemoryMethods(
972   AcquireMemoryHandler acquire_memory_handler,
973   ResizeMemoryHandler resize_memory_handler,
974   DestroyMemoryHandler destroy_memory_handler)
975 {
976   /*
977     Set memory methods.
978   */
979   if (acquire_memory_handler != (AcquireMemoryHandler) NULL)
980     memory_methods.acquire_memory_handler=acquire_memory_handler;
981   if (resize_memory_handler != (ResizeMemoryHandler) NULL)
982     memory_methods.resize_memory_handler=resize_memory_handler;
983   if (destroy_memory_handler != (DestroyMemoryHandler) NULL)
984     memory_methods.destroy_memory_handler=destroy_memory_handler;
985 }