MagickCore  7.0.9
memory.c
Go to the documentation of this file.
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 % Cristy %
17 % July 1998 %
18 % %
19 % %
20 % Copyright 1999-2019 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 % https://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_ANONYMOUS_MEMORY_SUPPORT
48 % to allocate memory with private anonymous mapping rather than from the
49 % heap.
50 %
51 */
52 
53 /*
54  Include declarations.
55 */
56 #include "MagickCore/studio.h"
57 #include "MagickCore/blob.h"
59 #include "MagickCore/exception.h"
61 #include "MagickCore/memory_.h"
63 #include "MagickCore/policy.h"
64 #include "MagickCore/resource_.h"
65 #include "MagickCore/semaphore.h"
66 #include "MagickCore/string_.h"
69 
70 /*
71  Define declarations.
72 */
73 #define BlockFooter(block,size) \
74  ((size_t *) ((char *) (block)+(size)-2*sizeof(size_t)))
75 #define BlockHeader(block) ((size_t *) (block)-1)
76 #define BlockSize 4096
77 #define BlockThreshold 1024
78 #define MaxBlockExponent 16
79 #define MaxBlocks ((BlockThreshold/(4*sizeof(size_t)))+MaxBlockExponent+1)
80 #define MaxSegments 1024
81 #define MemoryGuard ((0xdeadbeef << 31)+0xdeafdeed)
82 #define NextBlock(block) ((char *) (block)+SizeOfBlock(block))
83 #define NextBlockInList(block) (*(void **) (block))
84 #define PreviousBlock(block) ((char *) (block)-(*((size_t *) (block)-2)))
85 #define PreviousBlockBit 0x01
86 #define PreviousBlockInList(block) (*((void **) (block)+1))
87 #define SegmentSize (2*1024*1024)
88 #define SizeMask (~0x01)
89 #define SizeOfBlock(block) (*BlockHeader(block) & SizeMask)
90 
91 /*
92  Typedef declarations.
93 */
94 typedef enum
95 {
101 
102 typedef struct _DataSegmentInfo
103 {
104  void
106  *bound;
107 
110 
111  size_t
113 
115  *previous,
116  *next;
118 
119 typedef struct _MagickMemoryMethods
120 {
123 
126 
129 
132 
136 
138 {
139  char
141 
144 
145  size_t
147 
148  void
150 
151  size_t
153 };
154 
155 typedef struct _MemoryPool
156 {
157  size_t
159 
160  void
162 
163  size_t
165 
169 } MemoryPool;
170 
171 /*
172  Global declarations.
173 */
174 static size_t
177 
178 #if defined _MSC_VER
179 static void* MSCMalloc(size_t size)
180 {
181  return malloc(size);
182 }
183 static void* MSCRealloc(void* ptr, size_t size)
184 {
185  return realloc(ptr, size);
186 }
187 static void MSCFree(void* ptr)
188 {
189  free(ptr);
190 }
191 #endif
192 
193 static MagickMemoryMethods
195  {
196 #if defined _MSC_VER
197  (AcquireMemoryHandler) MSCMalloc,
198  (ResizeMemoryHandler) MSCRealloc,
199  (DestroyMemoryHandler) MSCFree,
200 #else
201  (AcquireMemoryHandler) malloc,
202  (ResizeMemoryHandler) realloc,
203  (DestroyMemoryHandler) free,
204 #endif
207  };
208 #if defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
209 static MemoryPool
210  memory_pool;
211 
212 static SemaphoreInfo
213  *memory_semaphore = (SemaphoreInfo *) NULL;
214 
215 static volatile DataSegmentInfo
216  *free_segments = (DataSegmentInfo *) NULL;
217 
218 /*
219  Forward declarations.
220 */
221 static MagickBooleanType
222  ExpandHeap(size_t);
223 #endif
224 
225 /*
226 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
227 % %
228 % %
229 % %
230 % A c q u i r e A l i g n e d M e m o r y %
231 % %
232 % %
233 % %
234 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
235 %
236 % AcquireAlignedMemory() returns a pointer to a block of memory at least size
237 % bytes whose address is aligned on a cache line or page boundary.
238 %
239 % The format of the AcquireAlignedMemory method is:
240 %
241 % void *AcquireAlignedMemory(const size_t count,const size_t quantum)
242 %
243 % A description of each parameter follows:
244 %
245 % o count: the number of quantum elements to allocate.
246 %
247 % o quantum: the number of bytes in each quantum.
248 %
249 */
250 MagickExport void *AcquireAlignedMemory(const size_t count,const size_t quantum)
251 {
252 #define AlignedExtent(size,alignment) \
253  (((size)+((alignment)-1)) & ~((alignment)-1))
254 #define AlignedPowerOf2(x) ((((x) - 1) & (x)) == 0)
255 
256  size_t
257  alignment,
258  extent,
259  size;
260 
261  void
262  *memory;
263 
264  if (HeapOverflowSanityCheck(count,quantum) != MagickFalse)
265  return((void *) NULL);
266  memory=NULL;
267  size=count*quantum;
268  alignment=CACHE_LINE_SIZE;
269  extent=AlignedExtent(size,alignment);
270  if ((size == 0) || (extent < size))
271  return((void *) NULL);
273  return(memory_methods.acquire_aligned_memory_handler(extent,alignment));
274 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
275  if (posix_memalign(&memory,alignment,extent) != 0)
276  memory=NULL;
277 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
278  memory=_aligned_malloc(extent,alignment);
279 #else
280  {
281  void
282  *p;
283 
284  if ((alignment == 0) || (alignment % sizeof(void *) != 0) ||
285  (AlignedPowerOf2(alignment/sizeof(void *)) == 0))
286  {
287  errno=EINVAL;
288  return((void *) NULL);
289  }
290  if (size > (SIZE_MAX-alignment-sizeof(void *)-1))
291  {
292  errno=ENOMEM;
293  return((void *) NULL);
294  }
295  extent=(size+alignment-1)+sizeof(void *);
296  if (extent > size)
297  {
298  p=AcquireMagickMemory(extent);
299  if (p != NULL)
300  {
301  memory=(void *) AlignedExtent((size_t) p+sizeof(void *),alignment);
302  *((void **) memory-1)=p;
303  }
304  }
305  }
306 #endif
307  return(memory);
308 }
309 
310 #if defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
311 /*
312 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
313 % %
314 % %
315 % %
316 + A c q u i r e B l o c k %
317 % %
318 % %
319 % %
320 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
321 %
322 % AcquireBlock() returns a pointer to a block of memory at least size bytes
323 % suitably aligned for any use.
324 %
325 % The format of the AcquireBlock method is:
326 %
327 % void *AcquireBlock(const size_t size)
328 %
329 % A description of each parameter follows:
330 %
331 % o size: the size of the memory in bytes to allocate.
332 %
333 */
334 
335 static inline size_t AllocationPolicy(size_t size)
336 {
337  register size_t
338  blocksize;
339 
340  /*
341  The linear distribution.
342  */
343  assert(size != 0);
344  assert(size % (4*sizeof(size_t)) == 0);
345  if (size <= BlockThreshold)
346  return(size/(4*sizeof(size_t)));
347  /*
348  Check for the largest block size.
349  */
350  if (size > (size_t) (BlockThreshold*(1L << (MaxBlockExponent-1L))))
351  return(MaxBlocks-1L);
352  /*
353  Otherwise use a power of two distribution.
354  */
355  blocksize=BlockThreshold/(4*sizeof(size_t));
356  for ( ; size > BlockThreshold; size/=2)
357  blocksize++;
358  assert(blocksize > (BlockThreshold/(4*sizeof(size_t))));
359  assert(blocksize < (MaxBlocks-1L));
360  return(blocksize);
361 }
362 
363 static inline void InsertFreeBlock(void *block,const size_t i)
364 {
365  register void
366  *next,
367  *previous;
368 
369  size_t
370  size;
371 
372  size=SizeOfBlock(block);
373  previous=(void *) NULL;
374  next=memory_pool.blocks[i];
375  while ((next != (void *) NULL) && (SizeOfBlock(next) < size))
376  {
377  previous=next;
378  next=NextBlockInList(next);
379  }
380  PreviousBlockInList(block)=previous;
381  NextBlockInList(block)=next;
382  if (previous != (void *) NULL)
383  NextBlockInList(previous)=block;
384  else
385  memory_pool.blocks[i]=block;
386  if (next != (void *) NULL)
387  PreviousBlockInList(next)=block;
388 }
389 
390 static inline void RemoveFreeBlock(void *block,const size_t i)
391 {
392  register void
393  *next,
394  *previous;
395 
396  next=NextBlockInList(block);
397  previous=PreviousBlockInList(block);
398  if (previous == (void *) NULL)
399  memory_pool.blocks[i]=next;
400  else
401  NextBlockInList(previous)=next;
402  if (next != (void *) NULL)
403  PreviousBlockInList(next)=previous;
404 }
405 
406 static void *AcquireBlock(size_t size)
407 {
408  register size_t
409  i;
410 
411  register void
412  *block;
413 
414  /*
415  Find free block.
416  */
417  size=(size_t) (size+sizeof(size_t)+6*sizeof(size_t)-1) & -(4U*sizeof(size_t));
418  i=AllocationPolicy(size);
419  block=memory_pool.blocks[i];
420  while ((block != (void *) NULL) && (SizeOfBlock(block) < size))
421  block=NextBlockInList(block);
422  if (block == (void *) NULL)
423  {
424  i++;
425  while (memory_pool.blocks[i] == (void *) NULL)
426  i++;
427  block=memory_pool.blocks[i];
428  if (i >= MaxBlocks)
429  return((void *) NULL);
430  }
431  assert((*BlockHeader(NextBlock(block)) & PreviousBlockBit) == 0);
432  assert(SizeOfBlock(block) >= size);
433  RemoveFreeBlock(block,AllocationPolicy(SizeOfBlock(block)));
434  if (SizeOfBlock(block) > size)
435  {
436  size_t
437  blocksize;
438 
439  void
440  *next;
441 
442  /*
443  Split block.
444  */
445  next=(char *) block+size;
446  blocksize=SizeOfBlock(block)-size;
447  *BlockHeader(next)=blocksize;
448  *BlockFooter(next,blocksize)=blocksize;
449  InsertFreeBlock(next,AllocationPolicy(blocksize));
450  *BlockHeader(block)=size | (*BlockHeader(block) & ~SizeMask);
451  }
452  assert(size == SizeOfBlock(block));
454  memory_pool.allocation+=size;
455  return(block);
456 }
457 #endif
458 
459 /*
460 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
461 % %
462 % %
463 % %
464 % A c q u i r e M a g i c k M e m o r y %
465 % %
466 % %
467 % %
468 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
469 %
470 % AcquireMagickMemory() returns a pointer to a block of memory at least size
471 % bytes suitably aligned for any use.
472 %
473 % The format of the AcquireMagickMemory method is:
474 %
475 % void *AcquireMagickMemory(const size_t size)
476 %
477 % A description of each parameter follows:
478 %
479 % o size: the size of the memory in bytes to allocate.
480 %
481 */
482 MagickExport void *AcquireMagickMemory(const size_t size)
483 {
484  register void
485  *memory;
486 
487 #if !defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
488  memory=memory_methods.acquire_memory_handler(size == 0 ? 1UL : size);
489 #else
490  if (memory_semaphore == (SemaphoreInfo *) NULL)
491  ActivateSemaphoreInfo(&memory_semaphore);
492  if (free_segments == (DataSegmentInfo *) NULL)
493  {
494  LockSemaphoreInfo(memory_semaphore);
495  if (free_segments == (DataSegmentInfo *) NULL)
496  {
497  register ssize_t
498  i;
499 
500  assert(2*sizeof(size_t) > (size_t) (~SizeMask));
501  (void) memset(&memory_pool,0,sizeof(memory_pool));
502  memory_pool.allocation=SegmentSize;
503  memory_pool.blocks[MaxBlocks]=(void *) (-1);
504  for (i=0; i < MaxSegments; i++)
505  {
506  if (i != 0)
507  memory_pool.segment_pool[i].previous=
508  (&memory_pool.segment_pool[i-1]);
509  if (i != (MaxSegments-1))
510  memory_pool.segment_pool[i].next=(&memory_pool.segment_pool[i+1]);
511  }
512  free_segments=(&memory_pool.segment_pool[0]);
513  }
514  UnlockSemaphoreInfo(memory_semaphore);
515  }
516  LockSemaphoreInfo(memory_semaphore);
517  memory=AcquireBlock(size == 0 ? 1UL : size);
518  if (memory == (void *) NULL)
519  {
520  if (ExpandHeap(size == 0 ? 1UL : size) != MagickFalse)
521  memory=AcquireBlock(size == 0 ? 1UL : size);
522  }
523  UnlockSemaphoreInfo(memory_semaphore);
524 #endif
525  return(memory);
526 }
527 
528 /*
529 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
530 % %
531 % %
532 % %
533 % A c q u i r e Q u a n t u m M e m o r y %
534 % %
535 % %
536 % %
537 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
538 %
539 % AcquireQuantumMemory() returns a pointer to a block of memory at least
540 % count * quantum bytes suitably aligned for any use.
541 %
542 % The format of the AcquireQuantumMemory method is:
543 %
544 % void *AcquireQuantumMemory(const size_t count,const size_t quantum)
545 %
546 % A description of each parameter follows:
547 %
548 % o count: the number of quantum elements to allocate.
549 %
550 % o quantum: the number of bytes in each quantum.
551 %
552 */
553 MagickExport void *AcquireQuantumMemory(const size_t count,const size_t quantum)
554 {
555  size_t
556  extent;
557 
558  if (HeapOverflowSanityCheck(count,quantum) != MagickFalse)
559  return((void *) NULL);
560  extent=count*quantum;
561  return(AcquireMagickMemory(extent));
562 }
563 
564 /*
565 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
566 % %
567 % %
568 % %
569 % A c q u i r e V i r t u a l M e m o r y %
570 % %
571 % %
572 % %
573 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
574 %
575 % AcquireVirtualMemory() allocates a pointer to a block of memory at least
576 % size bytes suitably aligned for any use. In addition to heap, it also
577 % supports memory-mapped and file-based memory-mapped memory requests.
578 %
579 % The format of the AcquireVirtualMemory method is:
580 %
581 % MemoryInfo *AcquireVirtualMemory(const size_t count,const size_t quantum)
582 %
583 % A description of each parameter follows:
584 %
585 % o count: the number of quantum elements to allocate.
586 %
587 % o quantum: the number of bytes in each quantum.
588 %
589 */
590 
592  const size_t quantum)
593 {
594  char
595  *value;
596 
597  MemoryInfo
598  *memory_info;
599 
600  size_t
601  extent;
602 
603  if (HeapOverflowSanityCheck(count,quantum) != MagickFalse)
604  return((MemoryInfo *) NULL);
605  if (virtual_anonymous_memory == 0)
606  {
608  value=GetPolicyValue("system:memory-map");
609  if (LocaleCompare(value,"anonymous") == 0)
610  {
611  /*
612  The security policy sets anonymous mapping for the memory request.
613  */
614 #if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
616 #endif
617  }
618  value=DestroyString(value);
619  }
621  sizeof(*memory_info)));
622  if (memory_info == (MemoryInfo *) NULL)
623  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
624  (void) memset(memory_info,0,sizeof(*memory_info));
625  extent=count*quantum;
626  memory_info->length=extent;
627  memory_info->signature=MagickCoreSignature;
628  if ((virtual_anonymous_memory == 1) &&
629  ((count*quantum) <= GetMaxMemoryRequest()))
630  {
631  memory_info->blob=AcquireAlignedMemory(1,extent);
632  if (memory_info->blob != NULL)
633  memory_info->type=AlignedVirtualMemory;
634  }
635  if (memory_info->blob == NULL)
636  {
637  /*
638  Acquire anonymous memory map.
639  */
640  memory_info->blob=NULL;
641  if ((count*quantum) <= GetMaxMemoryRequest())
642  memory_info->blob=MapBlob(-1,IOMode,0,extent);
643  if (memory_info->blob != NULL)
644  memory_info->type=MapVirtualMemory;
645  else
646  {
647  int
648  file;
649 
650  /*
651  Anonymous memory mapping failed, try file-backed memory mapping.
652  */
653  file=AcquireUniqueFileResource(memory_info->filename);
654  if (file != -1)
655  {
657  offset;
658 
659  offset=(MagickOffsetType) lseek(file,extent-1,SEEK_SET);
660  if ((offset == (MagickOffsetType) (extent-1)) &&
661  (write(file,"",1) == 1))
662  {
663 #if !defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
664  memory_info->blob=MapBlob(file,IOMode,0,extent);
665 #else
666  if (posix_fallocate(file,0,extent) == 0)
667  memory_info->blob=MapBlob(file,IOMode,0,extent);
668 #endif
669  if (memory_info->blob != NULL)
670  memory_info->type=MapVirtualMemory;
671  else
672  {
674  memory_info->filename);
675  *memory_info->filename='\0';
676  }
677  }
678  (void) close(file);
679  }
680  }
681  }
682  if (memory_info->blob == NULL)
683  {
684  memory_info->blob=AcquireQuantumMemory(1,extent);
685  if (memory_info->blob != NULL)
686  memory_info->type=UnalignedVirtualMemory;
687  }
688  if (memory_info->blob == NULL)
689  memory_info=RelinquishVirtualMemory(memory_info);
690  return(memory_info);
691 }
692 
693 /*
694 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
695 % %
696 % %
697 % %
698 % C o p y M a g i c k M e m o r y %
699 % %
700 % %
701 % %
702 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
703 %
704 % CopyMagickMemory() copies size bytes from memory area source to the
705 % destination. Copying between objects that overlap will take place
706 % correctly. It returns destination.
707 %
708 % The format of the CopyMagickMemory method is:
709 %
710 % void *CopyMagickMemory(void *destination,const void *source,
711 % const size_t size)
712 %
713 % A description of each parameter follows:
714 %
715 % o destination: the destination.
716 %
717 % o source: the source.
718 %
719 % o size: the size of the memory in bytes to allocate.
720 %
721 */
722 MagickExport void *CopyMagickMemory(void *destination,const void *source,
723  const size_t size)
724 {
725  register const unsigned char
726  *p;
727 
728  register unsigned char
729  *q;
730 
731  assert(destination != (void *) NULL);
732  assert(source != (const void *) NULL);
733  p=(const unsigned char *) source;
734  q=(unsigned char *) destination;
735  if (((q+size) < p) || (q > (p+size)))
736  switch (size)
737  {
738  default: return(memcpy(destination,source,size));
739  case 8: *q++=(*p++);
740  case 7: *q++=(*p++);
741  case 6: *q++=(*p++);
742  case 5: *q++=(*p++);
743  case 4: *q++=(*p++);
744  case 3: *q++=(*p++);
745  case 2: *q++=(*p++);
746  case 1: *q++=(*p++);
747  case 0: return(destination);
748  }
749  return(memmove(destination,source,size));
750 }
751 
752 /*
753 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
754 % %
755 % %
756 % %
757 + D e s t r o y M a g i c k M e m o r y %
758 % %
759 % %
760 % %
761 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
762 %
763 % DestroyMagickMemory() deallocates memory associated with the memory manager.
764 %
765 % The format of the DestroyMagickMemory method is:
766 %
767 % DestroyMagickMemory(void)
768 %
769 */
771 {
772 #if defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
773  register ssize_t
774  i;
775 
776  if (memory_semaphore == (SemaphoreInfo *) NULL)
777  ActivateSemaphoreInfo(&memory_semaphore);
778  LockSemaphoreInfo(memory_semaphore);
779  for (i=0; i < (ssize_t) memory_pool.number_segments; i++)
780  if (memory_pool.segments[i]->mapped == MagickFalse)
782  memory_pool.segments[i]->allocation);
783  else
784  (void) UnmapBlob(memory_pool.segments[i]->allocation,
785  memory_pool.segments[i]->length);
786  free_segments=(DataSegmentInfo *) NULL;
787  (void) memset(&memory_pool,0,sizeof(memory_pool));
788  UnlockSemaphoreInfo(memory_semaphore);
789  RelinquishSemaphoreInfo(&memory_semaphore);
790 #endif
791 }
792 
793 #if defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
794 /*
795 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
796 % %
797 % %
798 % %
799 + E x p a n d H e a p %
800 % %
801 % %
802 % %
803 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
804 %
805 % ExpandHeap() get more memory from the system. It returns MagickTrue on
806 % success otherwise MagickFalse.
807 %
808 % The format of the ExpandHeap method is:
809 %
810 % MagickBooleanType ExpandHeap(size_t size)
811 %
812 % A description of each parameter follows:
813 %
814 % o size: the size of the memory in bytes we require.
815 %
816 */
817 static MagickBooleanType ExpandHeap(size_t size)
818 {
820  *segment_info;
821 
823  mapped;
824 
825  register ssize_t
826  i;
827 
828  register void
829  *block;
830 
831  size_t
832  blocksize;
833 
834  void
835  *segment;
836 
837  blocksize=((size+12*sizeof(size_t))+SegmentSize-1) & -SegmentSize;
838  assert(memory_pool.number_segments < MaxSegments);
839  segment=MapBlob(-1,IOMode,0,blocksize);
840  mapped=segment != (void *) NULL ? MagickTrue : MagickFalse;
841  if (segment == (void *) NULL)
842  segment=(void *) memory_methods.acquire_memory_handler(blocksize);
843  if (segment == (void *) NULL)
844  return(MagickFalse);
845  segment_info=(DataSegmentInfo *) free_segments;
846  free_segments=segment_info->next;
847  segment_info->mapped=mapped;
848  segment_info->length=blocksize;
849  segment_info->allocation=segment;
850  segment_info->bound=(char *) segment+blocksize;
851  i=(ssize_t) memory_pool.number_segments-1;
852  for ( ; (i >= 0) && (memory_pool.segments[i]->allocation > segment); i--)
853  memory_pool.segments[i+1]=memory_pool.segments[i];
854  memory_pool.segments[i+1]=segment_info;
855  memory_pool.number_segments++;
856  size=blocksize-12*sizeof(size_t);
857  block=(char *) segment_info->allocation+4*sizeof(size_t);
858  *BlockHeader(block)=size | PreviousBlockBit;
859  *BlockFooter(block,size)=size;
860  InsertFreeBlock(block,AllocationPolicy(size));
861  block=NextBlock(block);
862  assert(block < segment_info->bound);
863  *BlockHeader(block)=2*sizeof(size_t);
865  return(MagickTrue);
866 }
867 #endif
868 
869 /*
870 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
871 % %
872 % %
873 % %
874 % G e t M a g i c k M e m o r y M e t h o d s %
875 % %
876 % %
877 % %
878 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
879 %
880 % GetMagickMemoryMethods() gets the methods to acquire, resize, and destroy
881 % memory.
882 %
883 % The format of the GetMagickMemoryMethods() method is:
884 %
885 % void GetMagickMemoryMethods(AcquireMemoryHandler *acquire_memory_handler,
886 % ResizeMemoryHandler *resize_memory_handler,
887 % DestroyMemoryHandler *destroy_memory_handler)
888 %
889 % A description of each parameter follows:
890 %
891 % o acquire_memory_handler: method to acquire memory (e.g. malloc).
892 %
893 % o resize_memory_handler: method to resize memory (e.g. realloc).
894 %
895 % o destroy_memory_handler: method to destroy memory (e.g. free).
896 %
897 */
899  AcquireMemoryHandler *acquire_memory_handler,
900  ResizeMemoryHandler *resize_memory_handler,
901  DestroyMemoryHandler *destroy_memory_handler)
902 {
903  assert(acquire_memory_handler != (AcquireMemoryHandler *) NULL);
904  assert(resize_memory_handler != (ResizeMemoryHandler *) NULL);
905  assert(destroy_memory_handler != (DestroyMemoryHandler *) NULL);
906  *acquire_memory_handler=memory_methods.acquire_memory_handler;
907  *resize_memory_handler=memory_methods.resize_memory_handler;
908  *destroy_memory_handler=memory_methods.destroy_memory_handler;
909 }
910 
911 /*
912 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
913 % %
914 % %
915 % %
916 + G e t M a x M e m o r y R e q u e s t %
917 % %
918 % %
919 % %
920 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
921 %
922 % GetMaxMemoryRequest() returns the max_memory_request value.
923 %
924 % The format of the GetMaxMemoryRequest method is:
925 %
926 % size_t GetMaxMemoryRequest(void)
927 %
928 */
930 {
931  if (max_memory_request == 0)
932  {
933  char
934  *value;
935 
936  value=GetPolicyValue("system:max-memory-request");
937  if (value != (char *) NULL)
938  {
939  /*
940  The security policy sets a max memory request limit.
941  */
943  value=DestroyString(value);
944  }
945  else
947  }
948  return(max_memory_request);
949 }
950 
951 /*
952 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
953 % %
954 % %
955 % %
956 % G e t V i r t u a l M e m o r y B l o b %
957 % %
958 % %
959 % %
960 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
961 %
962 % GetVirtualMemoryBlob() returns the virtual memory blob associated with the
963 % specified MemoryInfo structure.
964 %
965 % The format of the GetVirtualMemoryBlob method is:
966 %
967 % void *GetVirtualMemoryBlob(const MemoryInfo *memory_info)
968 %
969 % A description of each parameter follows:
970 %
971 % o memory_info: The MemoryInfo structure.
972 */
974 {
975  assert(memory_info != (const MemoryInfo *) NULL);
976  assert(memory_info->signature == MagickCoreSignature);
977  return(memory_info->blob);
978 }
979 
980 /*
981 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
982 % %
983 % %
984 % %
985 + H e a p O v e r f l o w S a n i t y C h e c k %
986 % %
987 % %
988 % %
989 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
990 %
991 % HeapOverflowSanityCheck() returns MagickTrue if the heap allocation request
992 % does not exceed the maximum limits of a size_t otherwise MagickFalse.
993 %
994 % The format of the HeapOverflowSanityCheck method is:
995 %
996 % MagickBooleanType HeapOverflowSanityCheck(const size_t count,
997 % const size_t quantum)
998 %
999 % A description of each parameter follows:
1000 %
1001 % o size: the size of the memory in bytes we require.
1002 %
1003 */
1005  const size_t quantum)
1006 {
1007  size_t
1008  size;
1009 
1010  size=count*quantum;
1011  if ((count == 0) || (quantum != (size/count)))
1012  {
1013  errno=ENOMEM;
1014  return(MagickTrue);
1015  }
1016  return(MagickFalse);
1017 }
1018 
1019 /*
1020 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1021 % %
1022 % %
1023 % %
1024 % R e l i n q u i s h A l i g n e d M e m o r y %
1025 % %
1026 % %
1027 % %
1028 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1029 %
1030 % RelinquishAlignedMemory() frees memory acquired with AcquireAlignedMemory()
1031 % or reuse.
1032 %
1033 % The format of the RelinquishAlignedMemory method is:
1034 %
1035 % void *RelinquishAlignedMemory(void *memory)
1036 %
1037 % A description of each parameter follows:
1038 %
1039 % o memory: A pointer to a block of memory to free for reuse.
1040 %
1041 */
1043 {
1044  if (memory == (void *) NULL)
1045  return((void *) NULL);
1047  {
1049  return(NULL);
1050  }
1051 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
1052  free(memory);
1053 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
1054  _aligned_free(memory);
1055 #else
1056  RelinquishMagickMemory(*((void **) memory-1));
1057 #endif
1058  return(NULL);
1059 }
1060 
1061 /*
1062 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1063 % %
1064 % %
1065 % %
1066 % R e l i n q u i s h M a g i c k M e m o r y %
1067 % %
1068 % %
1069 % %
1070 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1071 %
1072 % RelinquishMagickMemory() frees memory acquired with AcquireMagickMemory()
1073 % or AcquireQuantumMemory() for reuse.
1074 %
1075 % The format of the RelinquishMagickMemory method is:
1076 %
1077 % void *RelinquishMagickMemory(void *memory)
1078 %
1079 % A description of each parameter follows:
1080 %
1081 % o memory: A pointer to a block of memory to free for reuse.
1082 %
1083 */
1085 {
1086  if (memory == (void *) NULL)
1087  return((void *) NULL);
1088 #if !defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
1090 #else
1091  LockSemaphoreInfo(memory_semaphore);
1092  assert((SizeOfBlock(memory) % (4*sizeof(size_t))) == 0);
1093  assert((*BlockHeader(NextBlock(memory)) & PreviousBlockBit) != 0);
1094  if ((*BlockHeader(memory) & PreviousBlockBit) == 0)
1095  {
1096  void
1097  *previous;
1098 
1099  /*
1100  Coalesce with previous adjacent block.
1101  */
1102  previous=PreviousBlock(memory);
1103  RemoveFreeBlock(previous,AllocationPolicy(SizeOfBlock(previous)));
1104  *BlockHeader(previous)=(SizeOfBlock(previous)+SizeOfBlock(memory)) |
1105  (*BlockHeader(previous) & ~SizeMask);
1106  memory=previous;
1107  }
1108  if ((*BlockHeader(NextBlock(NextBlock(memory))) & PreviousBlockBit) == 0)
1109  {
1110  void
1111  *next;
1112 
1113  /*
1114  Coalesce with next adjacent block.
1115  */
1116  next=NextBlock(memory);
1117  RemoveFreeBlock(next,AllocationPolicy(SizeOfBlock(next)));
1118  *BlockHeader(memory)=(SizeOfBlock(memory)+SizeOfBlock(next)) |
1119  (*BlockHeader(memory) & ~SizeMask);
1120  }
1121  *BlockFooter(memory,SizeOfBlock(memory))=SizeOfBlock(memory);
1122  *BlockHeader(NextBlock(memory))&=(~PreviousBlockBit);
1123  InsertFreeBlock(memory,AllocationPolicy(SizeOfBlock(memory)));
1124  UnlockSemaphoreInfo(memory_semaphore);
1125 #endif
1126  return((void *) NULL);
1127 }
1128 
1129 /*
1130 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1131 % %
1132 % %
1133 % %
1134 % R e l i n q u i s h V i r t u a l M e m o r y %
1135 % %
1136 % %
1137 % %
1138 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1139 %
1140 % RelinquishVirtualMemory() frees memory acquired with AcquireVirtualMemory().
1141 %
1142 % The format of the RelinquishVirtualMemory method is:
1143 %
1144 % MemoryInfo *RelinquishVirtualMemory(MemoryInfo *memory_info)
1145 %
1146 % A description of each parameter follows:
1147 %
1148 % o memory_info: A pointer to a block of memory to free for reuse.
1149 %
1150 */
1152 {
1153  assert(memory_info != (MemoryInfo *) NULL);
1154  assert(memory_info->signature == MagickCoreSignature);
1155  if (memory_info->blob != (void *) NULL)
1156  switch (memory_info->type)
1157  {
1158  case AlignedVirtualMemory:
1159  {
1160  memory_info->blob=RelinquishAlignedMemory(memory_info->blob);
1161  break;
1162  }
1163  case MapVirtualMemory:
1164  {
1165  (void) UnmapBlob(memory_info->blob,memory_info->length);
1166  memory_info->blob=NULL;
1167  if (*memory_info->filename != '\0')
1168  (void) RelinquishUniqueFileResource(memory_info->filename);
1169  break;
1170  }
1172  default:
1173  {
1174  memory_info->blob=RelinquishMagickMemory(memory_info->blob);
1175  break;
1176  }
1177  }
1178  memory_info->signature=(~MagickCoreSignature);
1179  memory_info=(MemoryInfo *) RelinquishAlignedMemory(memory_info);
1180  return(memory_info);
1181 }
1182 
1183 /*
1184 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1185 % %
1186 % %
1187 % %
1188 % R e s e t M a g i c k M e m o r y %
1189 % %
1190 % %
1191 % %
1192 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1193 %
1194 % ResetMagickMemory() fills the first size bytes of the memory area pointed to
1195 % by memory with the constant byte c.
1196 %
1197 % The format of the ResetMagickMemory method is:
1198 %
1199 % void *ResetMagickMemory(void *memory,int byte,const size_t size)
1200 %
1201 % A description of each parameter follows:
1202 %
1203 % o memory: a pointer to a memory allocation.
1204 %
1205 % o byte: set the memory to this value.
1206 %
1207 % o size: size of the memory to reset.
1208 %
1209 */
1210 MagickExport void *ResetMagickMemory(void *memory,int byte,const size_t size)
1211 {
1212  assert(memory != (void *) NULL);
1213  return(memset(memory,byte,size));
1214 }
1215 
1216 /*
1217 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1218 % %
1219 % %
1220 % %
1221 + R e s e t M a x M e m o r y R e q u e s t %
1222 % %
1223 % %
1224 % %
1225 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1226 %
1227 % ResetMaxMemoryRequest() resets the max_memory_request value.
1228 %
1229 % The format of the ResetMaxMemoryRequest method is:
1230 %
1231 % void ResetMaxMemoryRequest(void)
1232 %
1233 */
1235 {
1237 }
1238 
1239 /*
1240 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1241 % %
1242 % %
1243 % %
1244 + R e s e t V i r t u a l A n o n y m o u s M e m o r y %
1245 % %
1246 % %
1247 % %
1248 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1249 %
1250 % ResetVirtualAnonymousMemory() resets the virtual_anonymous_memory value.
1251 %
1252 % The format of the ResetVirtualAnonymousMemory method is:
1253 %
1254 % void ResetVirtualAnonymousMemory(void)
1255 %
1256 */
1258 {
1260 }
1261 
1262 /*
1263 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1264 % %
1265 % %
1266 % %
1267 % R e s i z e M a g i c k M e m o r y %
1268 % %
1269 % %
1270 % %
1271 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1272 %
1273 % ResizeMagickMemory() changes the size of the memory and returns a pointer to
1274 % the (possibly moved) block. The contents will be unchanged up to the
1275 % lesser of the new and old sizes.
1276 %
1277 % The format of the ResizeMagickMemory method is:
1278 %
1279 % void *ResizeMagickMemory(void *memory,const size_t size)
1280 %
1281 % A description of each parameter follows:
1282 %
1283 % o memory: A pointer to a memory allocation.
1284 %
1285 % o size: the new size of the allocated memory.
1286 %
1287 */
1288 
1289 #if defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
1290 static inline void *ResizeBlock(void *block,size_t size)
1291 {
1292  register void
1293  *memory;
1294 
1295  if (block == (void *) NULL)
1296  return(AcquireBlock(size));
1297  memory=AcquireBlock(size);
1298  if (memory == (void *) NULL)
1299  return((void *) NULL);
1300  if (size <= (SizeOfBlock(block)-sizeof(size_t)))
1301  (void) memcpy(memory,block,size);
1302  else
1303  (void) memcpy(memory,block,SizeOfBlock(block)-sizeof(size_t));
1304  memory_pool.allocation+=size;
1305  return(memory);
1306 }
1307 #endif
1308 
1309 MagickExport void *ResizeMagickMemory(void *memory,const size_t size)
1310 {
1311  register void
1312  *block;
1313 
1314  if (memory == (void *) NULL)
1315  return(AcquireMagickMemory(size));
1316 #if !defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
1317  block=memory_methods.resize_memory_handler(memory,size == 0 ? 1UL : size);
1318  if (block == (void *) NULL)
1319  memory=RelinquishMagickMemory(memory);
1320 #else
1321  LockSemaphoreInfo(memory_semaphore);
1322  block=ResizeBlock(memory,size == 0 ? 1UL : size);
1323  if (block == (void *) NULL)
1324  {
1325  if (ExpandHeap(size == 0 ? 1UL : size) == MagickFalse)
1326  {
1327  UnlockSemaphoreInfo(memory_semaphore);
1328  memory=RelinquishMagickMemory(memory);
1329  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1330  }
1331  block=ResizeBlock(memory,size == 0 ? 1UL : size);
1332  assert(block != (void *) NULL);
1333  }
1334  UnlockSemaphoreInfo(memory_semaphore);
1335  memory=RelinquishMagickMemory(memory);
1336 #endif
1337  return(block);
1338 }
1339 
1340 /*
1341 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1342 % %
1343 % %
1344 % %
1345 % R e s i z e Q u a n t u m M e m o r y %
1346 % %
1347 % %
1348 % %
1349 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1350 %
1351 % ResizeQuantumMemory() changes the size of the memory and returns a pointer
1352 % to the (possibly moved) block. The contents will be unchanged up to the
1353 % lesser of the new and old sizes.
1354 %
1355 % The format of the ResizeQuantumMemory method is:
1356 %
1357 % void *ResizeQuantumMemory(void *memory,const size_t count,
1358 % const size_t quantum)
1359 %
1360 % A description of each parameter follows:
1361 %
1362 % o memory: A pointer to a memory allocation.
1363 %
1364 % o count: the number of quantum elements to allocate.
1365 %
1366 % o quantum: the number of bytes in each quantum.
1367 %
1368 */
1369 MagickExport void *ResizeQuantumMemory(void *memory,const size_t count,
1370  const size_t quantum)
1371 {
1372  size_t
1373  extent;
1374 
1375  if (HeapOverflowSanityCheck(count,quantum) != MagickFalse)
1376  {
1377  memory=RelinquishMagickMemory(memory);
1378  return((void *) NULL);
1379  }
1380  extent=count*quantum;
1381  return(ResizeMagickMemory(memory,extent));
1382 }
1383 
1384 /*
1385 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1386 % %
1387 % %
1388 % %
1389 % S e t M a g i c k A l i g n e d M e m o r y M e t h o d s %
1390 % %
1391 % %
1392 % %
1393 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1394 %
1395 % SetMagickAlignedMemoryMethods() sets the methods to acquire and relinquish
1396 % aligned memory.
1397 %
1398 % The format of the SetMagickAlignedMemoryMethods() method is:
1399 %
1400 % SetMagickAlignedMemoryMethods(
1401 % AcquireAlignedMemoryHandler acquire_aligned_memory_handler,
1402 % RelinquishAlignedMemoryHandler relinquish_aligned_memory_handler)
1403 %
1404 % A description of each parameter follows:
1405 %
1406 % o acquire_memory_handler: method to acquire aligned memory.
1407 %
1408 % o relinquish_aligned_memory_handler: method to relinquish aligned memory.
1409 %
1410 */
1412  AcquireAlignedMemoryHandler acquire_aligned_memory_handler,
1413  RelinquishAlignedMemoryHandler relinquish_aligned_memory_handler)
1414 {
1415  memory_methods.acquire_aligned_memory_handler=acquire_aligned_memory_handler;
1417  relinquish_aligned_memory_handler;
1418 }
1419 
1420 /*
1421 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1422 % %
1423 % %
1424 % %
1425 % S e t M a g i c k M e m o r y M e t h o d s %
1426 % %
1427 % %
1428 % %
1429 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1430 %
1431 % SetMagickMemoryMethods() sets the methods to acquire, resize, and destroy
1432 % memory. Your custom memory methods must be set prior to the
1433 % MagickCoreGenesis() method.
1434 %
1435 % The format of the SetMagickMemoryMethods() method is:
1436 %
1437 % SetMagickMemoryMethods(AcquireMemoryHandler acquire_memory_handler,
1438 % ResizeMemoryHandler resize_memory_handler,
1439 % DestroyMemoryHandler destroy_memory_handler)
1440 %
1441 % A description of each parameter follows:
1442 %
1443 % o acquire_memory_handler: method to acquire memory (e.g. malloc).
1444 %
1445 % o resize_memory_handler: method to resize memory (e.g. realloc).
1446 %
1447 % o destroy_memory_handler: method to destroy memory (e.g. free).
1448 %
1449 */
1451  AcquireMemoryHandler acquire_memory_handler,
1452  ResizeMemoryHandler resize_memory_handler,
1453  DestroyMemoryHandler destroy_memory_handler)
1454 {
1455  /*
1456  Set memory methods.
1457  */
1458  if (acquire_memory_handler != (AcquireMemoryHandler) NULL)
1459  memory_methods.acquire_memory_handler=acquire_memory_handler;
1460  if (resize_memory_handler != (ResizeMemoryHandler) NULL)
1461  memory_methods.resize_memory_handler=resize_memory_handler;
1462  if (destroy_memory_handler != (DestroyMemoryHandler) NULL)
1463  memory_methods.destroy_memory_handler=destroy_memory_handler;
1464 }
char filename[MagickPathExtent]
Definition: memory.c:140
void * blob
Definition: memory.c:149
MagickExport MemoryInfo * RelinquishVirtualMemory(MemoryInfo *memory_info)
Definition: memory.c:1151
static size_t StringToSizeType(const char *string, const double interval)
MagickExport void DestroyMagickMemory(void)
Definition: memory.c:770
static size_t max_memory_request
Definition: memory.c:175
MagickExport void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info)
Definition: semaphore.c:450
#define MagickAssumeAligned(address)
#define CACHE_LINE_SIZE
MagickExport void SetMagickMemoryMethods(AcquireMemoryHandler acquire_memory_handler, ResizeMemoryHandler resize_memory_handler, DestroyMemoryHandler destroy_memory_handler)
Definition: memory.c:1450
#define MagickULLConstant(c)
Definition: magick-type.h:36
#define MaxSegments
Definition: memory.c:80
#define ThrowFatalException(severity, tag)
MagickExport MemoryInfo * AcquireVirtualMemory(const size_t count, const size_t quantum)
Definition: memory.c:591
#define BlockThreshold
Definition: memory.c:77
void * bound
Definition: memory.c:105
Definition: blob.h:32
static MagickMemoryMethods memory_methods
Definition: memory.c:194
#define SegmentSize
Definition: memory.c:87
AcquireMemoryHandler acquire_memory_handler
Definition: memory.c:122
struct _MagickMemoryMethods MagickMemoryMethods
MagickExport void GetMagickMemoryMethods(AcquireMemoryHandler *acquire_memory_handler, ResizeMemoryHandler *resize_memory_handler, DestroyMemoryHandler *destroy_memory_handler)
Definition: memory.c:898
AcquireAlignedMemoryHandler acquire_aligned_memory_handler
Definition: memory.c:131
void *(*)(* DestroyMemoryHandler)(void *)
Definition: memory_.h:30
MagickExport void * ResizeMagickMemory(void *memory, const size_t size)
Definition: memory.c:1309
MagickExport void * ResizeQuantumMemory(void *memory, const size_t count, const size_t quantum)
Definition: memory.c:1369
ssize_t MagickOffsetType
Definition: magick-type.h:129
#define SizeOfBlock(block)
Definition: memory.c:89
#define NextBlockInList(block)
Definition: memory.c:83
#define BlockFooter(block, size)
Definition: memory.c:73
ResizeMemoryHandler resize_memory_handler
Definition: memory.c:125
#define MagickCoreSignature
#define NextBlock(block)
Definition: memory.c:82
MagickExport void LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
Definition: semaphore.c:293
size_t number_segments
Definition: memory.c:164
struct _DataSegmentInfo * next
Definition: memory.c:114
void * allocation
Definition: memory.c:105
MagickExport MagickBooleanType HeapOverflowSanityCheck(const size_t, const size_t)
Definition: memory.c:1004
MagickBooleanType
Definition: magick-type.h:158
MagickExport int AcquireUniqueFileResource(char *path)
Definition: resource.c:548
MagickExport void * ResetMagickMemory(void *memory, int byte, const size_t size)
Definition: memory.c:1210
#define SizeMask
Definition: memory.c:88
MagickExport void * AcquireQuantumMemory(const size_t count, const size_t quantum)
Definition: memory.c:553
MagickExport MagickBooleanType RelinquishUniqueFileResource(const char *path)
Definition: resource.c:1095
DataSegmentInfo segment_pool[MaxSegments]
Definition: memory.c:167
#define MagickPathExtent
MagickExport void * RelinquishAlignedMemory(void *memory)
Definition: memory.c:1042
DataSegmentInfo * segments[MaxSegments]
Definition: memory.c:167
DestroyMemoryHandler destroy_memory_handler
Definition: memory.c:128
size_t allocation
Definition: memory.c:158
size_t length
Definition: memory.c:146
RelinquishAlignedMemoryHandler relinquish_aligned_memory_handler
Definition: memory.c:134
#define MaxBlocks
Definition: memory.c:79
MagickExport void * AcquireAlignedMemory(const size_t count, const size_t quantum)
Definition: memory.c:250
MagickExport int LocaleCompare(const char *p, const char *q)
Definition: locale.c:1435
struct _DataSegmentInfo * previous
Definition: memory.c:114
#define PreviousBlock(block)
Definition: memory.c:84
size_t length
Definition: memory.c:112
#define BlockHeader(block)
Definition: memory.c:75
#define PreviousBlockBit
Definition: memory.c:85
size_t signature
Definition: memory.c:152
VirtualMemoryType
Definition: memory.c:94
void * blocks[MaxBlocks+1]
Definition: memory.c:161
MagickExport char * DestroyString(char *string)
Definition: string.c:823
MagickExport void * AcquireMagickMemory(const size_t size)
Definition: memory.c:482
MagickExport void ActivateSemaphoreInfo(SemaphoreInfo **semaphore_info)
Definition: semaphore.c:97
static size_t virtual_anonymous_memory
Definition: memory.c:176
#define AlignedPowerOf2(x)
MagickExport void SetMagickAlignedMemoryMethods(AcquireAlignedMemoryHandler acquire_aligned_memory_handler, RelinquishAlignedMemoryHandler relinquish_aligned_memory_handler)
Definition: memory.c:1411
void *(*)(*)*(*)*(*)(* RelinquishAlignedMemoryHandler)(void *)
Definition: memory_.h:33
MagickExport char * GetPolicyValue(const char *name)
Definition: policy.c:506
struct _DataSegmentInfo DataSegmentInfo
MagickExport void * RelinquishMagickMemory(void *memory)
Definition: memory.c:1084
MagickExport MagickBooleanType UnmapBlob(void *, const size_t)
Definition: blob.c:5493
#define AlignedExtent(size, alignment)
#define MaxBlockExponent
Definition: memory.c:78
MagickExport size_t GetMaxMemoryRequest(void)
Definition: memory.c:929
#define MagickPrivate
#define MagickExport
VirtualMemoryType type
Definition: memory.c:143
MagickPrivate void ResetMaxMemoryRequest(void)
MagickExport void * GetVirtualMemoryBlob(const MemoryInfo *memory_info)
Definition: memory.c:973
MagickBooleanType mapped
Definition: memory.c:109
void *(*)(*)*(* ResizeMemoryHandler)(void *, size_t) magick_alloc_size(2)
Definition: memory_.h:31
MagickExport void RelinquishSemaphoreInfo(SemaphoreInfo **semaphore_info)
Definition: semaphore.c:351
struct _MemoryPool MemoryPool
MagickPrivate void ResetVirtualAnonymousMemory(void)
Definition: memory.c:1257
MagickExport void * CopyMagickMemory(void *destination, const void *source, const size_t size)
Definition: memory.c:722
void *(*)(*)*(*)*(* AcquireAlignedMemoryHandler)(const size_t, const size_t)
Definition: memory_.h:32
#define PreviousBlockInList(block)
Definition: memory.c:86
MagickExport void * MapBlob(int, const MapMode, const MagickOffsetType, const size_t)
void *(* AcquireMemoryHandler)(size_t) magick_alloc_size(1)
Definition: memory_.h:29