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