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