83#include "MagickCore/studio.h"
84#include "MagickCore/blob.h"
85#include "MagickCore/blob-private.h"
86#include "MagickCore/exception.h"
87#include "MagickCore/exception-private.h"
88#include "MagickCore/image-private.h"
89#include "MagickCore/memory_.h"
90#include "MagickCore/memory-private.h"
91#include "MagickCore/policy.h"
92#include "MagickCore/resource_.h"
93#include "MagickCore/semaphore.h"
94#include "MagickCore/string_.h"
95#include "MagickCore/string-private.h"
96#include "MagickCore/utility-private.h"
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)
122 UndefinedVirtualMemory,
123 AlignedVirtualMemory,
125 UnalignedVirtualMemory
148 acquire_memory_handler;
151 resize_memory_handler;
154 destroy_memory_handler;
156 AcquireAlignedMemoryHandler
157 acquire_aligned_memory_handler;
159 RelinquishAlignedMemoryHandler
160 relinquish_aligned_memory_handler;
166 filename[MagickPathExtent];
187 *blocks[MaxBlocks+1];
193 *segments[MaxSegments],
194 segment_pool[MaxSegments];
201 max_memory_request = 0,
202 virtual_anonymous_memory = 0;
205static void *MSCMalloc(
size_t size)
207 return(malloc(size));
210static void *MSCRealloc(
void* ptr,
size_t size)
212 return(realloc(ptr,size));
215static void MSCFree(
void* ptr)
225 (AcquireMemoryHandler) MSCMalloc,
226 (ResizeMemoryHandler) MSCRealloc,
227 (DestroyMemoryHandler) MSCFree,
229 (AcquireMemoryHandler) malloc,
230 (ResizeMemoryHandler) realloc,
231 (DestroyMemoryHandler) free,
233 (AcquireAlignedMemoryHandler) NULL,
234 (RelinquishAlignedMemoryHandler) NULL
236#if defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
249static MagickBooleanType
278#if defined(MAGICKCORE_HAVE_ALIGNED_MALLOC)
279#define AcquireAlignedMemory_Actual AcquireAlignedMemory_STDC
280static inline void *AcquireAlignedMemory_STDC(
const size_t size)
283 extent = CACHE_ALIGNED(size);
290 return(aligned_alloc(CACHE_LINE_SIZE,extent));
292#elif defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
293#define AcquireAlignedMemory_Actual AcquireAlignedMemory_POSIX
294static inline void *AcquireAlignedMemory_POSIX(
const size_t size)
299 if (posix_memalign(&memory,CACHE_LINE_SIZE,size))
303#elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
304#define AcquireAlignedMemory_Actual AcquireAlignedMemory_WinAPI
305static inline void *AcquireAlignedMemory_WinAPI(
const size_t size)
307 return(_aligned_malloc(size,CACHE_LINE_SIZE));
310#define ALIGNMENT_OVERHEAD \
311 (MAGICKCORE_MAX_ALIGNMENT_PADDING(CACHE_LINE_SIZE) + MAGICKCORE_SIZEOF_VOID_P)
312static inline void *reserve_space_for_actual_base_address(
void *
const p)
314 return((
void **) p+1);
317static inline void **pointer_to_space_for_actual_base_address(
void *
const p)
319 return((
void **) p-1);
322static inline void *actual_base_address(
void *
const p)
324 return(*pointer_to_space_for_actual_base_address(p));
327static inline void *align_to_cache(
void *
const p)
329 return((
void *) CACHE_ALIGNED((MagickAddressType) p));
332static inline void *adjust(
void *
const p)
334 return(align_to_cache(reserve_space_for_actual_base_address(p)));
337#define AcquireAlignedMemory_Actual AcquireAlignedMemory_Generic
338static inline void *AcquireAlignedMemory_Generic(
const size_t size)
347 #if SIZE_MAX < ALIGNMENT_OVERHEAD
348 #error "CACHE_LINE_SIZE is way too big."
350 extent=(size+ALIGNMENT_OVERHEAD);
356 p=AcquireMagickMemory(extent);
360 *pointer_to_space_for_actual_base_address(memory)=p;
365MagickExport
void *AcquireAlignedMemory(
const size_t count,
const size_t quantum)
370 if (HeapOverflowSanityCheckGetSize(count,quantum,&size) != MagickFalse)
375 if (memory_methods.acquire_aligned_memory_handler != (AcquireAlignedMemoryHandler) NULL)
376 return(memory_methods.acquire_aligned_memory_handler(size,CACHE_LINE_SIZE));
377 return(AcquireAlignedMemory_Actual(size));
380#if defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
405static inline size_t AllocationPolicy(
size_t size)
414 assert(size % (4*
sizeof(
size_t)) == 0);
415 if (size <= BlockThreshold)
416 return(size/(4*
sizeof(
size_t)));
420 if (size > (
size_t) (BlockThreshold*(1L << (MaxBlockExponent-1L))))
421 return(MaxBlocks-1L);
425 blocksize=BlockThreshold/(4*
sizeof(size_t));
426 for ( ; size > BlockThreshold; size/=2)
428 assert(blocksize > (BlockThreshold/(4*
sizeof(
size_t))));
429 assert(blocksize < (MaxBlocks-1L));
433static inline void InsertFreeBlock(
void *block,
const size_t i)
442 size=SizeOfBlock(block);
443 previous=(
void *) NULL;
444 next=memory_pool.blocks[i];
445 while ((next != (
void *) NULL) && (SizeOfBlock(next) < size))
448 next=NextBlockInList(next);
450 PreviousBlockInList(block)=previous;
451 NextBlockInList(block)=next;
452 if (previous != (
void *) NULL)
453 NextBlockInList(previous)=block;
455 memory_pool.blocks[i]=block;
456 if (next != (
void *) NULL)
457 PreviousBlockInList(next)=block;
460static inline void RemoveFreeBlock(
void *block,
const size_t i)
466 next=NextBlockInList(block);
467 previous=PreviousBlockInList(block);
468 if (previous == (
void *) NULL)
469 memory_pool.blocks[i]=next;
471 NextBlockInList(previous)=next;
472 if (next != (
void *) NULL)
473 PreviousBlockInList(next)=previous;
476static void *AcquireBlock(
size_t size)
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)
495 while (memory_pool.blocks[i] == (
void *) NULL)
497 block=memory_pool.blocks[i];
499 return((
void *) NULL);
501 assert((*BlockHeader(NextBlock(block)) & PreviousBlockBit) == 0);
502 assert(SizeOfBlock(block) >= size);
503 RemoveFreeBlock(block,AllocationPolicy(SizeOfBlock(block)));
504 if (SizeOfBlock(block) > size)
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);
522 assert(size == SizeOfBlock(block));
523 *BlockHeader(NextBlock(block))|=PreviousBlockBit;
524 memory_pool.allocation+=size;
552MagickExport
void *AcquireMagickMemory(
const size_t size)
557#if !defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
558 memory=memory_methods.acquire_memory_handler(size == 0 ? 1UL : size);
561 ActivateSemaphoreInfo(&memory_semaphore);
564 LockSemaphoreInfo(memory_semaphore);
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++)
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]);
582 free_segments=(&memory_pool.segment_pool[0]);
584 UnlockSemaphoreInfo(memory_semaphore);
586 LockSemaphoreInfo(memory_semaphore);
587 memory=AcquireBlock(size == 0 ? 1UL : size);
588 if (memory == (
void *) NULL)
590 if (ExpandHeap(size == 0 ? 1UL : size) != MagickFalse)
591 memory=AcquireBlock(size == 0 ? 1UL : size);
593 UnlockSemaphoreInfo(memory_semaphore);
626MagickExport
void *AcquireCriticalMemory(
const size_t size)
634 memory=AcquireMagickMemory(size);
635 if (memory == (
void *) NULL)
636 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
665MagickExport
void *AcquireQuantumMemory(
const size_t count,
const size_t quantum)
670 if ((HeapOverflowSanityCheckGetSize(count,quantum,&size) != MagickFalse) ||
671 (size > GetMaxMemoryRequest()))
676 return(AcquireMagickMemory(size));
705MagickExport
MemoryInfo *AcquireVirtualMemory(
const size_t count,
706 const size_t quantum)
717 if (HeapOverflowSanityCheckGetSize(count,quantum,&size) != MagickFalse)
722 if (virtual_anonymous_memory == 0)
724 virtual_anonymous_memory=1;
725 value=GetPolicyValue(
"system:memory-map");
726 if (LocaleCompare(value,
"anonymous") == 0)
731#if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
732 virtual_anonymous_memory=2;
735 value=DestroyString(value);
737 memory_info=(
MemoryInfo *) MagickAssumeAligned(AcquireAlignedMemory(1,
738 sizeof(*memory_info)));
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()))
746 memory_info->blob=AcquireAlignedMemory(1,size);
747 if (memory_info->blob != NULL)
748 memory_info->type=AlignedVirtualMemory;
750 if (memory_info->blob == NULL)
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;
768 file=AcquireUniqueFileResource(memory_info->filename);
774 offset=(MagickOffsetType) lseek(file,(off_t) (size-1),SEEK_SET);
775 if ((offset == (MagickOffsetType) (size-1)) &&
776 (write(file,
"",1) == 1))
778#if !defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
779 memory_info->blob=MapBlob(file,IOMode,0,size);
781 if (posix_fallocate(file,0,(MagickOffsetType) size) == 0)
782 memory_info->blob=MapBlob(file,IOMode,0,size);
784 if (memory_info->blob != NULL)
785 memory_info->type=MapVirtualMemory;
788 (void) RelinquishUniqueFileResource(
789 memory_info->filename);
790 *memory_info->filename=
'\0';
797 if (memory_info->blob == NULL)
799 memory_info->blob=AcquireQuantumMemory(1,size);
800 if (memory_info->blob != NULL)
801 memory_info->type=UnalignedVirtualMemory;
803 if (memory_info->blob == NULL)
804 memory_info=RelinquishVirtualMemory(memory_info);
837MagickExport
void *CopyMagickMemory(
void *magick_restrict destination,
838 const void *magick_restrict source,
const size_t size)
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)))
853 default:
return(memcpy(destination,source,size));
854 case 8: *q++=(*p++); magick_fallthrough;
855 case 7: *q++=(*p++); magick_fallthrough;
856 case 6: *q++=(*p++); magick_fallthrough;
857 case 5: *q++=(*p++); magick_fallthrough;
858 case 4: *q++=(*p++); magick_fallthrough;
859 case 3: *q++=(*p++); magick_fallthrough;
860 case 2: *q++=(*p++); magick_fallthrough;
861 case 1: *q++=(*p++); magick_fallthrough;
862 case 0:
return(destination);
864 return(memmove(destination,source,size));
885MagickExport
void DestroyMagickMemory(
void)
887#if defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
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)
896 memory_methods.destroy_memory_handler(
897 memory_pool.segments[i]->allocation);
899 (
void) UnmapBlob(memory_pool.segments[i]->allocation,
900 memory_pool.segments[i]->length);
902 (void) memset(&memory_pool,0,
sizeof(memory_pool));
903 UnlockSemaphoreInfo(memory_semaphore);
904 RelinquishSemaphoreInfo(&memory_semaphore);
908#if defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
932static MagickBooleanType ExpandHeap(
size_t size)
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)
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);
979 *BlockHeader(NextBlock(block))=PreviousBlockBit;
1013MagickExport
void GetMagickMemoryMethods(
1014 AcquireMemoryHandler *acquire_memory_handler,
1015 ResizeMemoryHandler *resize_memory_handler,
1016 DestroyMemoryHandler *destroy_memory_handler)
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;
1044MagickExport
size_t GetMaxMemoryRequest(
void)
1046#define MinMemoryRequest "16MiB"
1048 if (max_memory_request == 0)
1053 max_memory_request=(size_t) MAGICK_SSIZE_MAX;
1054 value=GetPolicyValue(
"system:max-memory-request");
1055 if (value != (
char *) NULL)
1060 max_memory_request=MagickMax(StringToSizeType(value,100.0),
1061 StringToSizeType(MinMemoryRequest,100.0));
1062 value=DestroyString(value);
1065 return(MagickMin(max_memory_request,(
size_t) MAGICK_SSIZE_MAX));
1090MagickExport
void *GetVirtualMemoryBlob(
const MemoryInfo *memory_info)
1092 assert(memory_info != (
const MemoryInfo *) NULL);
1093 assert(memory_info->signature == MagickCoreSignature);
1094 return(memory_info->blob);
1120MagickExport
void *RelinquishAlignedMemory(
void *memory)
1122 if (memory == (
void *) NULL)
1123 return((
void *) NULL);
1124 if (memory_methods.relinquish_aligned_memory_handler != (RelinquishAlignedMemoryHandler) NULL)
1126 memory_methods.relinquish_aligned_memory_handler(memory);
1129#if defined(MAGICKCORE_HAVE_ALIGNED_MALLOC) || defined(MAGICKCORE_HAVE_POSIX_MEMALIGN)
1131#elif defined(MAGICKCORE_HAVE__ALIGNED_MALLOC)
1132 _aligned_free(memory);
1134 RelinquishMagickMemory(actual_base_address(memory));
1162MagickExport
void *RelinquishMagickMemory(
void *memory)
1164 if (memory == (
void *) NULL)
1165 return((
void *) NULL);
1166#if !defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
1167 memory_methods.destroy_memory_handler(memory);
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)
1180 previous=PreviousBlock(memory);
1181 RemoveFreeBlock(previous,AllocationPolicy(SizeOfBlock(previous)));
1182 *BlockHeader(previous)=(SizeOfBlock(previous)+SizeOfBlock(memory)) |
1183 (*BlockHeader(previous) & ~SizeMask);
1186 if ((*BlockHeader(NextBlock(NextBlock(memory))) & PreviousBlockBit) == 0)
1194 next=NextBlock(memory);
1195 RemoveFreeBlock(next,AllocationPolicy(SizeOfBlock(next)));
1196 *BlockHeader(memory)=(SizeOfBlock(memory)+SizeOfBlock(next)) |
1197 (*BlockHeader(memory) & ~SizeMask);
1199 *BlockFooter(memory,SizeOfBlock(memory))=SizeOfBlock(memory);
1200 *BlockHeader(NextBlock(memory))&=(~PreviousBlockBit);
1201 InsertFreeBlock(memory,AllocationPolicy(SizeOfBlock(memory)));
1202 UnlockSemaphoreInfo(memory_semaphore);
1204 return((
void *) NULL);
1232 assert(memory_info->signature == MagickCoreSignature);
1233 if (memory_info->blob != (
void *) NULL)
1234 switch (memory_info->type)
1236 case AlignedVirtualMemory:
1238 (void) ShredMagickMemory(memory_info->blob,memory_info->length);
1239 memory_info->blob=RelinquishAlignedMemory(memory_info->blob);
1242 case MapVirtualMemory:
1244 (void) UnmapBlob(memory_info->blob,memory_info->length);
1245 memory_info->blob=NULL;
1246 if (*memory_info->filename !=
'\0')
1247 (void) RelinquishUniqueFileResource(memory_info->filename);
1250 case UnalignedVirtualMemory:
1253 (void) ShredMagickMemory(memory_info->blob,memory_info->length);
1254 memory_info->blob=RelinquishMagickMemory(memory_info->blob);
1258 memory_info->signature=(~MagickCoreSignature);
1259 memory_info=(
MemoryInfo *) RelinquishAlignedMemory(memory_info);
1260 return(memory_info);
1292MagickExport
void *ResetMagickMemory(
void *memory,
int c,
const size_t size)
1294 volatile unsigned char
1295 *p = (
volatile unsigned char *) memory;
1300 assert(memory != (
void *) NULL);
1302 *p++=(
unsigned char) c;
1324MagickPrivate
void ResetMaxMemoryRequest(
void)
1326 max_memory_request=0;
1347MagickPrivate
void ResetVirtualAnonymousMemory(
void)
1349 virtual_anonymous_memory=0;
1379#if defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
1380static inline void *ResizeBlock(
void *block,
size_t size)
1385 if (block == (
void *) NULL)
1386 return(AcquireBlock(size));
1387 memory=AcquireBlock(size);
1388 if (memory == (
void *) NULL)
1389 return((
void *) NULL);
1390 if (size <= (SizeOfBlock(block)-
sizeof(
size_t)))
1391 (void) memcpy(memory,block,size);
1393 (
void) memcpy(memory,block,SizeOfBlock(block)-
sizeof(
size_t));
1394 memory_pool.allocation+=size;
1399MagickExport
void *ResizeMagickMemory(
void *memory,
const size_t size)
1404 if (memory == (
void *) NULL)
1405 return(AcquireMagickMemory(size));
1406#if !defined(MAGICKCORE_ANONYMOUS_MEMORY_SUPPORT)
1407 block=memory_methods.resize_memory_handler(memory,size == 0 ? 1UL : size);
1408 if (block == (
void *) NULL)
1409 memory=RelinquishMagickMemory(memory);
1411 LockSemaphoreInfo(memory_semaphore);
1412 block=ResizeBlock(memory,size == 0 ? 1UL : size);
1413 if (block == (
void *) NULL)
1415 if (ExpandHeap(size == 0 ? 1UL : size) == MagickFalse)
1417 UnlockSemaphoreInfo(memory_semaphore);
1418 memory=RelinquishMagickMemory(memory);
1419 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
1421 block=ResizeBlock(memory,size == 0 ? 1UL : size);
1422 assert(block != (
void *) NULL);
1424 UnlockSemaphoreInfo(memory_semaphore);
1425 memory=RelinquishMagickMemory(memory);
1459MagickExport
void *ResizeQuantumMemory(
void *memory,
const size_t count,
1460 const size_t quantum)
1465 if ((HeapOverflowSanityCheckGetSize(count,quantum,&size) != MagickFalse) ||
1466 (size > GetMaxMemoryRequest()))
1469 memory=RelinquishMagickMemory(memory);
1472 return(ResizeMagickMemory(memory,size));
1502MagickExport
void SetMagickAlignedMemoryMethods(
1503 AcquireAlignedMemoryHandler acquire_aligned_memory_handler,
1504 RelinquishAlignedMemoryHandler relinquish_aligned_memory_handler)
1506 memory_methods.acquire_aligned_memory_handler=acquire_aligned_memory_handler;
1507 memory_methods.relinquish_aligned_memory_handler=
1508 relinquish_aligned_memory_handler;
1541MagickExport
void SetMagickMemoryMethods(
1542 AcquireMemoryHandler acquire_memory_handler,
1543 ResizeMemoryHandler resize_memory_handler,
1544 DestroyMemoryHandler destroy_memory_handler)
1549 if (acquire_memory_handler != (AcquireMemoryHandler) NULL)
1550 memory_methods.acquire_memory_handler=acquire_memory_handler;
1551 if (resize_memory_handler != (ResizeMemoryHandler) NULL)
1552 memory_methods.resize_memory_handler=resize_memory_handler;
1553 if (destroy_memory_handler != (DestroyMemoryHandler) NULL)
1554 memory_methods.destroy_memory_handler=destroy_memory_handler;
1579MagickPrivate
void SetMaxMemoryRequest(
const MagickSizeType limit)
1581 max_memory_request=MagickMin(limit,GetMaxMemoryRequest());
1610MagickPrivate MagickBooleanType ShredMagickMemory(
void *memory,
1611 const size_t length)
1628 if ((memory == NULL) || (length == 0))
1629 return(MagickFalse);
1636 property=GetEnvironmentValue(
"MAGICK_SHRED_PASSES");
1637 if (property != (
char *) NULL)
1639 passes=(ssize_t) StringToInteger(property);
1640 property=DestroyString(property);
1642 property=GetPolicyValue(
"system:shred");
1643 if (property != (
char *) NULL)
1645 passes=(ssize_t) StringToInteger(property);
1646 property=DestroyString(property);
1654 quantum=(size_t) MagickMin(length,MagickMinBufferExtent);
1655 random_info=AcquireRandomInfo();
1656 key=GetRandomKey(random_info,quantum);
1657 for (i=0; i < passes; i++)
1663 *p = (
unsigned char *) memory;
1665 for (j=0; j < length; j+=quantum)
1668 SetRandomKey(random_info,quantum,GetStringInfoDatum(key));
1669 (void) memcpy(p,GetStringInfoDatum(key),(size_t)
1670 MagickMin(quantum,length-j));
1676 key=DestroyStringInfo(key);
1677 random_info=DestroyRandomInfo(random_info);
1678 return(i < passes ? MagickFalse : MagickTrue);