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