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 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  }
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)
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 (max_memory_request == 0)
586  {
588  value=GetPolicyValue("system:max-memory-request");
589  if (value != (char *) NULL)
590  {
591  /*
592  The security policy sets a max memory request limit.
593  */
595  value=DestroyString(value);
596  }
597  }
598  if (virtual_anonymous_memory == 0)
599  {
601  value=GetPolicyValue("system:memory-map");
602  if (LocaleCompare(value,"anonymous") == 0)
603  {
604  /*
605  The security policy sets anonymous mapping for the memory request.
606  */
607 #if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
609 #endif
610  }
611  value=DestroyString(value);
612  }
614  sizeof(*memory_info)));
615  if (memory_info == (MemoryInfo *) NULL)
616  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
617  (void) memset(memory_info,0,sizeof(*memory_info));
618  extent=count*quantum;
619  memory_info->length=extent;
620  memory_info->signature=MagickCoreSignature;
621  if ((virtual_anonymous_memory == 1) &&
622  ((count*quantum) <= (size_t) max_memory_request))
623  {
624  memory_info->blob=AcquireAlignedMemory(1,extent);
625  if (memory_info->blob != NULL)
626  memory_info->type=AlignedVirtualMemory;
627  }
628  if (memory_info->blob == NULL)
629  {
630  /*
631  Acquire anonymous memory map.
632  */
633  memory_info->blob=NULL;
634  if ((count*quantum) <= (size_t) max_memory_request)
635  memory_info->blob=MapBlob(-1,IOMode,0,extent);
636  if (memory_info->blob != NULL)
637  memory_info->type=MapVirtualMemory;
638  else
639  {
640  int
641  file;
642 
643  /*
644  Anonymous memory mapping failed, try file-backed memory mapping.
645  */
646  file=AcquireUniqueFileResource(memory_info->filename);
647  if (file != -1)
648  {
650  offset;
651 
652  offset=(MagickOffsetType) lseek(file,extent-1,SEEK_SET);
653  if ((offset == (MagickOffsetType) (extent-1)) &&
654  (write(file,"",1) == 1))
655  {
656  memory_info->blob=MapBlob(file,IOMode,0,extent);
657  if (memory_info->blob != NULL)
658  memory_info->type=MapVirtualMemory;
659  else
660  {
662  memory_info->filename);
663  *memory_info->filename='\0';
664  }
665  }
666  (void) close(file);
667  }
668  }
669  }
670  if (memory_info->blob == NULL)
671  {
672  memory_info->blob=AcquireQuantumMemory(1,extent);
673  if (memory_info->blob != NULL)
674  memory_info->type=UnalignedVirtualMemory;
675  }
676  if (memory_info->blob == NULL)
677  memory_info=RelinquishVirtualMemory(memory_info);
678  return(memory_info);
679 }
680 
681 /*
682 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
683 % %
684 % %
685 % %
686 % C o p y M a g i c k M e m o r y %
687 % %
688 % %
689 % %
690 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
691 %
692 % CopyMagickMemory() copies size bytes from memory area source to the
693 % destination. Copying between objects that overlap will take place
694 % correctly. It returns destination.
695 %
696 % The format of the CopyMagickMemory method is:
697 %
698 % void *CopyMagickMemory(void *destination,const void *source,
699 % const size_t size)
700 %
701 % A description of each parameter follows:
702 %
703 % o destination: the destination.
704 %
705 % o source: the source.
706 %
707 % o size: the size of the memory in bytes to allocate.
708 %
709 */
710 MagickExport void *CopyMagickMemory(void *destination,const void *source,
711  const size_t size)
712 {
713  register const unsigned char
714  *p;
715 
716  register unsigned char
717  *q;
718 
719  assert(destination != (void *) NULL);
720  assert(source != (const void *) NULL);
721  p=(const unsigned char *) source;
722  q=(unsigned char *) destination;
723  if (((q+size) < p) || (q > (p+size)))
724  switch (size)
725  {
726  default: return(memcpy(destination,source,size));
727  case 8: *q++=(*p++);
728  case 7: *q++=(*p++);
729  case 6: *q++=(*p++);
730  case 5: *q++=(*p++);
731  case 4: *q++=(*p++);
732  case 3: *q++=(*p++);
733  case 2: *q++=(*p++);
734  case 1: *q++=(*p++);
735  case 0: return(destination);
736  }
737  return(memmove(destination,source,size));
738 }
739 
740 /*
741 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
742 % %
743 % %
744 % %
745 + D e s t r o y M a g i c k M e m o r y %
746 % %
747 % %
748 % %
749 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
750 %
751 % DestroyMagickMemory() deallocates memory associated with the memory manager.
752 %
753 % The format of the DestroyMagickMemory method is:
754 %
755 % DestroyMagickMemory(void)
756 %
757 */
759 {
760 #if defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
761  register ssize_t
762  i;
763 
764  if (memory_semaphore == (SemaphoreInfo *) NULL)
765  ActivateSemaphoreInfo(&memory_semaphore);
766  LockSemaphoreInfo(memory_semaphore);
767  for (i=0; i < (ssize_t) memory_pool.number_segments; i++)
768  if (memory_pool.segments[i]->mapped == MagickFalse)
770  memory_pool.segments[i]->allocation);
771  else
772  (void) UnmapBlob(memory_pool.segments[i]->allocation,
773  memory_pool.segments[i]->length);
774  free_segments=(DataSegmentInfo *) NULL;
775  (void) memset(&memory_pool,0,sizeof(memory_pool));
776  UnlockSemaphoreInfo(memory_semaphore);
777  RelinquishSemaphoreInfo(&memory_semaphore);
778 #endif
779 }
780 
781 #if defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
782 /*
783 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
784 % %
785 % %
786 % %
787 + E x p a n d H e a p %
788 % %
789 % %
790 % %
791 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
792 %
793 % ExpandHeap() get more memory from the system. It returns MagickTrue on
794 % success otherwise MagickFalse.
795 %
796 % The format of the ExpandHeap method is:
797 %
798 % MagickBooleanType ExpandHeap(size_t size)
799 %
800 % A description of each parameter follows:
801 %
802 % o size: the size of the memory in bytes we require.
803 %
804 */
805 static MagickBooleanType ExpandHeap(size_t size)
806 {
808  *segment_info;
809 
811  mapped;
812 
813  register ssize_t
814  i;
815 
816  register void
817  *block;
818 
819  size_t
820  blocksize;
821 
822  void
823  *segment;
824 
825  blocksize=((size+12*sizeof(size_t))+SegmentSize-1) & -SegmentSize;
826  assert(memory_pool.number_segments < MaxSegments);
827  segment=MapBlob(-1,IOMode,0,blocksize);
828  mapped=segment != (void *) NULL ? MagickTrue : MagickFalse;
829  if (segment == (void *) NULL)
830  segment=(void *) memory_methods.acquire_memory_handler(blocksize);
831  if (segment == (void *) NULL)
832  return(MagickFalse);
833  segment_info=(DataSegmentInfo *) free_segments;
834  free_segments=segment_info->next;
835  segment_info->mapped=mapped;
836  segment_info->length=blocksize;
837  segment_info->allocation=segment;
838  segment_info->bound=(char *) segment+blocksize;
839  i=(ssize_t) memory_pool.number_segments-1;
840  for ( ; (i >= 0) && (memory_pool.segments[i]->allocation > segment); i--)
841  memory_pool.segments[i+1]=memory_pool.segments[i];
842  memory_pool.segments[i+1]=segment_info;
843  memory_pool.number_segments++;
844  size=blocksize-12*sizeof(size_t);
845  block=(char *) segment_info->allocation+4*sizeof(size_t);
846  *BlockHeader(block)=size | PreviousBlockBit;
847  *BlockFooter(block,size)=size;
848  InsertFreeBlock(block,AllocationPolicy(size));
849  block=NextBlock(block);
850  assert(block < segment_info->bound);
851  *BlockHeader(block)=2*sizeof(size_t);
853  return(MagickTrue);
854 }
855 #endif
856 
857 /*
858 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
859 % %
860 % %
861 % %
862 % G e t M a g i c k M e m o r y M e t h o d s %
863 % %
864 % %
865 % %
866 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
867 %
868 % GetMagickMemoryMethods() gets the methods to acquire, resize, and destroy
869 % memory.
870 %
871 % The format of the GetMagickMemoryMethods() method is:
872 %
873 % void GetMagickMemoryMethods(AcquireMemoryHandler *acquire_memory_handler,
874 % ResizeMemoryHandler *resize_memory_handler,
875 % DestroyMemoryHandler *destroy_memory_handler)
876 %
877 % A description of each parameter follows:
878 %
879 % o acquire_memory_handler: method to acquire memory (e.g. malloc).
880 %
881 % o resize_memory_handler: method to resize memory (e.g. realloc).
882 %
883 % o destroy_memory_handler: method to destroy memory (e.g. free).
884 %
885 */
887  AcquireMemoryHandler *acquire_memory_handler,
888  ResizeMemoryHandler *resize_memory_handler,
889  DestroyMemoryHandler *destroy_memory_handler)
890 {
891  assert(acquire_memory_handler != (AcquireMemoryHandler *) NULL);
892  assert(resize_memory_handler != (ResizeMemoryHandler *) NULL);
893  assert(destroy_memory_handler != (DestroyMemoryHandler *) NULL);
894  *acquire_memory_handler=memory_methods.acquire_memory_handler;
895  *resize_memory_handler=memory_methods.resize_memory_handler;
896  *destroy_memory_handler=memory_methods.destroy_memory_handler;
897 }
898 
899 /*
900 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
901 % %
902 % %
903 % %
904 % G e t V i r t u a l M e m o r y B l o b %
905 % %
906 % %
907 % %
908 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
909 %
910 % GetVirtualMemoryBlob() returns the virtual memory blob associated with the
911 % specified MemoryInfo structure.
912 %
913 % The format of the GetVirtualMemoryBlob method is:
914 %
915 % void *GetVirtualMemoryBlob(const MemoryInfo *memory_info)
916 %
917 % A description of each parameter follows:
918 %
919 % o memory_info: The MemoryInfo structure.
920 */
922 {
923  assert(memory_info != (const MemoryInfo *) NULL);
924  assert(memory_info->signature == MagickCoreSignature);
925  return(memory_info->blob);
926 }
927 
928 /*
929 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
930 % %
931 % %
932 % %
933 + H e a p O v e r f l o w S a n i t y C h e c k %
934 % %
935 % %
936 % %
937 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
938 %
939 % HeapOverflowSanityCheck() returns MagickTrue if the heap allocation request
940 % does not exceed the maximum limits of a size_t otherwise MagickFalse.
941 %
942 % The format of the HeapOverflowSanityCheck method is:
943 %
944 % MagickBooleanType HeapOverflowSanityCheck(const size_t count,
945 % const size_t quantum)
946 %
947 % A description of each parameter follows:
948 %
949 % o size: the size of the memory in bytes we require.
950 %
951 */
953  const size_t quantum)
954 {
955  size_t
956  size;
957 
958  size=count*quantum;
959  if ((count == 0) || (quantum != (size/count)))
960  {
961  errno=ENOMEM;
962  return(MagickTrue);
963  }
964  return(MagickFalse);
965 }
966 
967 /*
968 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
969 % %
970 % %
971 % %
972 % R e l i n q u i s h A l i g n e d M e m o r y %
973 % %
974 % %
975 % %
976 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
977 %
978 % RelinquishAlignedMemory() frees memory acquired with AcquireAlignedMemory()
979 % or reuse.
980 %
981 % The format of the RelinquishAlignedMemory method is:
982 %
983 % void *RelinquishAlignedMemory(void *memory)
984 %
985 % A description of each parameter follows:
986 %
987 % o memory: A pointer to a block of memory to free for reuse.
988 %
989 */
991 {
992  if (memory == (void *) NULL)
993  return((void *) NULL);
994 #if defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
995  free(memory);
996 #elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
997  _aligned_free(memory);
998 #else
999  free(*((void **) memory-1));
1000 #endif
1001  return(NULL);
1002 }
1003 
1004 /*
1005 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1006 % %
1007 % %
1008 % %
1009 % R e l i n q u i s h M a g i c k M e m o r y %
1010 % %
1011 % %
1012 % %
1013 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1014 %
1015 % RelinquishMagickMemory() frees memory acquired with AcquireMagickMemory()
1016 % or AcquireQuantumMemory() for reuse.
1017 %
1018 % The format of the RelinquishMagickMemory method is:
1019 %
1020 % void *RelinquishMagickMemory(void *memory)
1021 %
1022 % A description of each parameter follows:
1023 %
1024 % o memory: A pointer to a block of memory to free for reuse.
1025 %
1026 */
1028 {
1029  if (memory == (void *) NULL)
1030  return((void *) NULL);
1031 #if !defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
1033 #else
1034  LockSemaphoreInfo(memory_semaphore);
1035  assert((SizeOfBlock(memory) % (4*sizeof(size_t))) == 0);
1036  assert((*BlockHeader(NextBlock(memory)) & PreviousBlockBit) != 0);
1037  if ((*BlockHeader(memory) & PreviousBlockBit) == 0)
1038  {
1039  void
1040  *previous;
1041 
1042  /*
1043  Coalesce with previous adjacent block.
1044  */
1045  previous=PreviousBlock(memory);
1046  RemoveFreeBlock(previous,AllocationPolicy(SizeOfBlock(previous)));
1047  *BlockHeader(previous)=(SizeOfBlock(previous)+SizeOfBlock(memory)) |
1048  (*BlockHeader(previous) & ~SizeMask);
1049  memory=previous;
1050  }
1051  if ((*BlockHeader(NextBlock(NextBlock(memory))) & PreviousBlockBit) == 0)
1052  {
1053  void
1054  *next;
1055 
1056  /*
1057  Coalesce with next adjacent block.
1058  */
1059  next=NextBlock(memory);
1060  RemoveFreeBlock(next,AllocationPolicy(SizeOfBlock(next)));
1061  *BlockHeader(memory)=(SizeOfBlock(memory)+SizeOfBlock(next)) |
1062  (*BlockHeader(memory) & ~SizeMask);
1063  }
1064  *BlockFooter(memory,SizeOfBlock(memory))=SizeOfBlock(memory);
1065  *BlockHeader(NextBlock(memory))&=(~PreviousBlockBit);
1066  InsertFreeBlock(memory,AllocationPolicy(SizeOfBlock(memory)));
1067  UnlockSemaphoreInfo(memory_semaphore);
1068 #endif
1069  return((void *) NULL);
1070 }
1071 
1072 /*
1073 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1074 % %
1075 % %
1076 % %
1077 % R e l i n q u i s h V i r t u a l M e m o r y %
1078 % %
1079 % %
1080 % %
1081 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1082 %
1083 % RelinquishVirtualMemory() frees memory acquired with AcquireVirtualMemory().
1084 %
1085 % The format of the RelinquishVirtualMemory method is:
1086 %
1087 % MemoryInfo *RelinquishVirtualMemory(MemoryInfo *memory_info)
1088 %
1089 % A description of each parameter follows:
1090 %
1091 % o memory_info: A pointer to a block of memory to free for reuse.
1092 %
1093 */
1095 {
1096  assert(memory_info != (MemoryInfo *) NULL);
1097  assert(memory_info->signature == MagickCoreSignature);
1098  if (memory_info->blob != (void *) NULL)
1099  switch (memory_info->type)
1100  {
1101  case AlignedVirtualMemory:
1102  {
1103  memory_info->blob=RelinquishAlignedMemory(memory_info->blob);
1104  break;
1105  }
1106  case MapVirtualMemory:
1107  {
1108  (void) UnmapBlob(memory_info->blob,memory_info->length);
1109  memory_info->blob=NULL;
1110  if (*memory_info->filename != '\0')
1111  (void) RelinquishUniqueFileResource(memory_info->filename);
1112  break;
1113  }
1115  default:
1116  {
1117  memory_info->blob=RelinquishMagickMemory(memory_info->blob);
1118  break;
1119  }
1120  }
1121  memory_info->signature=(~MagickCoreSignature);
1122  memory_info=(MemoryInfo *) RelinquishAlignedMemory(memory_info);
1123  return(memory_info);
1124 }
1125 
1126 /*
1127 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1128 % %
1129 % %
1130 % %
1131 % R e s e t M a g i c k M e m o r y %
1132 % %
1133 % %
1134 % %
1135 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1136 %
1137 % ResetMagickMemory() fills the first size bytes of the memory area pointed to
1138 % by memory with the constant byte c.
1139 %
1140 % The format of the ResetMagickMemory method is:
1141 %
1142 % void *ResetMagickMemory(void *memory,int byte,const size_t size)
1143 %
1144 % A description of each parameter follows:
1145 %
1146 % o memory: a pointer to a memory allocation.
1147 %
1148 % o byte: set the memory to this value.
1149 %
1150 % o size: size of the memory to reset.
1151 %
1152 */
1153 MagickExport void *ResetMagickMemory(void *memory,int byte,const size_t size)
1154 {
1155  assert(memory != (void *) NULL);
1156  return(memset(memory,byte,size));
1157 }
1158 
1159 /*
1160 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1161 % %
1162 % %
1163 % %
1164 + R e s e t M a x M e m o r y R e q u e s t %
1165 % %
1166 % %
1167 % %
1168 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1169 %
1170 % ResetMaxMemoryRequest() resets the anonymous_memory value.
1171 %
1172 % The format of the ResetMaxMemoryRequest method is:
1173 %
1174 % void ResetMaxMemoryRequest(void)
1175 %
1176 */
1178 {
1180 }
1181 
1182 /*
1183 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1184 % %
1185 % %
1186 % %
1187 + 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 %
1188 % %
1189 % %
1190 % %
1191 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1192 %
1193 % ResetVirtualAnonymousMemory() resets the anonymous_memory value.
1194 %
1195 % The format of the ResetVirtualAnonymousMemory method is:
1196 %
1197 % void ResetVirtualAnonymousMemory(void)
1198 %
1199 */
1201 {
1203 }
1204 
1205 /*
1206 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1207 % %
1208 % %
1209 % %
1210 % R e s i z e M a g i c k M e m o r y %
1211 % %
1212 % %
1213 % %
1214 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1215 %
1216 % ResizeMagickMemory() changes the size of the memory and returns a pointer to
1217 % the (possibly moved) block. The contents will be unchanged up to the
1218 % lesser of the new and old sizes.
1219 %
1220 % The format of the ResizeMagickMemory method is:
1221 %
1222 % void *ResizeMagickMemory(void *memory,const size_t size)
1223 %
1224 % A description of each parameter follows:
1225 %
1226 % o memory: A pointer to a memory allocation.
1227 %
1228 % o size: the new size of the allocated memory.
1229 %
1230 */
1231 
1232 #if defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
1233 static inline void *ResizeBlock(void *block,size_t size)
1234 {
1235  register void
1236  *memory;
1237 
1238  if (block == (void *) NULL)
1239  return(AcquireBlock(size));
1240  memory=AcquireBlock(size);
1241  if (memory == (void *) NULL)
1242  return((void *) NULL);
1243  if (size <= (SizeOfBlock(block)-sizeof(size_t)))
1244  (void) memcpy(memory,block,size);
1245  else
1246  (void) memcpy(memory,block,SizeOfBlock(block)-sizeof(size_t));
1247  memory_pool.allocation+=size;
1248  return(memory);
1249 }
1250 #endif
1251 
1252 MagickExport void *ResizeMagickMemory(void *memory,const size_t size)
1253 {
1254  register void
1255  *block;
1256 
1257  if (memory == (void *) NULL)
1258  return(AcquireMagickMemory(size));
1259 #if !defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
1260  block=memory_methods.resize_memory_handler(memory,size == 0 ? 1UL : size);
1261  if (block == (void *) NULL)
1262  memory=RelinquishMagickMemory(memory);
1263 #else
1264  LockSemaphoreInfo(memory_semaphore);
1265  block=ResizeBlock(memory,size == 0 ? 1UL : size);
1266  if (block == (void *) NULL)
1267  {
1268  if (ExpandHeap(size == 0 ? 1UL : size) == MagickFalse)
1269  {
1270  UnlockSemaphoreInfo(memory_semaphore);
1271  memory=RelinquishMagickMemory(memory);
1272  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1273  }
1274  block=ResizeBlock(memory,size == 0 ? 1UL : size);
1275  assert(block != (void *) NULL);
1276  }
1277  UnlockSemaphoreInfo(memory_semaphore);
1278  memory=RelinquishMagickMemory(memory);
1279 #endif
1280  return(block);
1281 }
1282 
1283 /*
1284 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1285 % %
1286 % %
1287 % %
1288 % R e s i z e Q u a n t u m M e m o r y %
1289 % %
1290 % %
1291 % %
1292 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1293 %
1294 % ResizeQuantumMemory() changes the size of the memory and returns a pointer
1295 % to the (possibly moved) block. The contents will be unchanged up to the
1296 % lesser of the new and old sizes.
1297 %
1298 % The format of the ResizeQuantumMemory method is:
1299 %
1300 % void *ResizeQuantumMemory(void *memory,const size_t count,
1301 % const size_t quantum)
1302 %
1303 % A description of each parameter follows:
1304 %
1305 % o memory: A pointer to a memory allocation.
1306 %
1307 % o count: the number of quantum elements to allocate.
1308 %
1309 % o quantum: the number of bytes in each quantum.
1310 %
1311 */
1312 MagickExport void *ResizeQuantumMemory(void *memory,const size_t count,
1313  const size_t quantum)
1314 {
1315  size_t
1316  extent;
1317 
1318  if (HeapOverflowSanityCheck(count,quantum) != MagickFalse)
1319  {
1320  memory=RelinquishMagickMemory(memory);
1321  return((void *) NULL);
1322  }
1323  extent=count*quantum;
1324  return(ResizeMagickMemory(memory,extent));
1325 }
1326 
1327 /*
1328 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1329 % %
1330 % %
1331 % %
1332 % S e t M a g i c k M e m o r y M e t h o d s %
1333 % %
1334 % %
1335 % %
1336 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1337 %
1338 % SetMagickMemoryMethods() sets the methods to acquire, resize, and destroy
1339 % memory. Your custom memory methods must be set prior to the
1340 % MagickCoreGenesis() method.
1341 %
1342 % The format of the SetMagickMemoryMethods() method is:
1343 %
1344 % SetMagickMemoryMethods(AcquireMemoryHandler acquire_memory_handler,
1345 % ResizeMemoryHandler resize_memory_handler,
1346 % DestroyMemoryHandler destroy_memory_handler)
1347 %
1348 % A description of each parameter follows:
1349 %
1350 % o acquire_memory_handler: method to acquire memory (e.g. malloc).
1351 %
1352 % o resize_memory_handler: method to resize memory (e.g. realloc).
1353 %
1354 % o destroy_memory_handler: method to destroy memory (e.g. free).
1355 %
1356 */
1358  AcquireMemoryHandler acquire_memory_handler,
1359  ResizeMemoryHandler resize_memory_handler,
1360  DestroyMemoryHandler destroy_memory_handler)
1361 {
1362  /*
1363  Set memory methods.
1364  */
1365  if (acquire_memory_handler != (AcquireMemoryHandler) NULL)
1366  memory_methods.acquire_memory_handler=acquire_memory_handler;
1367  if (resize_memory_handler != (ResizeMemoryHandler) NULL)
1368  memory_methods.resize_memory_handler=resize_memory_handler;
1369  if (destroy_memory_handler != (DestroyMemoryHandler) NULL)
1370  memory_methods.destroy_memory_handler=destroy_memory_handler;
1371 }
char filename[MagickPathExtent]
Definition: memory.c:134
void * blob
Definition: memory.c:143
MagickExport MemoryInfo * RelinquishVirtualMemory(MemoryInfo *memory_info)
Definition: memory.c:1094
static size_t StringToSizeType(const char *string, const double interval)
MagickExport void DestroyMagickMemory(void)
Definition: memory.c:758
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:1200
MagickExport void SetMagickMemoryMethods(AcquireMemoryHandler acquire_memory_handler, ResizeMemoryHandler resize_memory_handler, DestroyMemoryHandler destroy_memory_handler)
Definition: memory.c:1357
#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:886
MagickExport void * ResizeMagickMemory(void *memory, const size_t size)
Definition: memory.c:1252
MagickExport void * ResizeQuantumMemory(void *memory, const size_t count, const size_t quantum)
Definition: memory.c:1312
MagickPrivate void ResetMaxMemoryRequest(void)
Definition: memory.c:1177
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:952
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:1153
#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:990
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:1408
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:816
MagickExport void * AcquireMagickMemory(const size_t size)
Definition: memory.c:462
MagickExport void ActivateSemaphoreInfo(SemaphoreInfo **semaphore_info)
Definition: semaphore.c:97
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:1027
MagickExport MagickBooleanType UnmapBlob(void *, const size_t)
Definition: blob.c:5274
#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:921
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:710
#define PreviousBlockInList(block)
Definition: memory.c:86
MagickExport void * MapBlob(int, const MapMode, const MagickOffsetType, const size_t)