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