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