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