% MagickCore Memory Allocation Methods %
% %
% Software Design %
-% John Cristy %
+% Cristy %
% July 1998 %
% %
% %
-% Copyright 1999-2013 ImageMagick Studio LLC, a non-profit organization %
+% Copyright 1999-2015 ImageMagick Studio LLC, a non-profit organization %
% dedicated to making software imaging solutions freely available. %
% %
% You may not use this file except in compliance with the License. You may %
#include "MagickCore/resource_.h"
#include "MagickCore/semaphore.h"
#include "MagickCore/string_.h"
+#include "MagickCore/utility-private.h"
\f
/*
Define declarations.
/*
Typedef declarations.
*/
+typedef enum
+{
+ UndefinedVirtualMemory,
+ AlignedVirtualMemory,
+ MapVirtualMemory,
+ UnalignedVirtualMemory
+} VirtualMemoryType;
+
typedef struct _DataSegmentInfo
{
void
destroy_memory_handler;
} MagickMemoryMethods;
-typedef struct _MemoryInfo
+struct _MemoryInfo
{
char
- filename[MaxTextExtent];
+ filename[MagickPathExtent];
- MagickBooleanType
- mapped;
+ VirtualMemoryType
+ type;
+
+ size_t
+ length;
void
*blob;
size_t
signature;
-} MemoryInfo;
+};
typedef struct _MemoryPool
{
/*
Global declarations.
*/
+#if defined _MSC_VER
+static void* MSCMalloc(size_t size)
+{
+ return malloc(size);
+}
+static void* MSCRealloc(void* ptr, size_t size)
+{
+ return realloc(ptr, size);
+}
+static void MSCFree(void* ptr)
+{
+ free(ptr);
+}
+#endif
+
static MagickMemoryMethods
memory_methods =
{
+#if defined _MSC_VER
+ (AcquireMemoryHandler) MSCMalloc,
+ (ResizeMemoryHandler) MSCRealloc,
+ (DestroyMemoryHandler) MSCFree
+#else
(AcquireMemoryHandler) malloc,
(ResizeMemoryHandler) realloc,
(DestroyMemoryHandler) free
+#endif
};
-
#if defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
static MemoryPool
memory_pool;
memory=memory_methods.acquire_memory_handler(size == 0 ? 1UL : size);
#else
if (memory_semaphore == (SemaphoreInfo *) NULL)
- AcquireSemaphoreInfo(&memory_semaphore);
+ ActivateSemaphoreInfo(&memory_semaphore);
if (free_segments == (DataSegmentInfo *) NULL)
{
LockSemaphoreInfo(memory_semaphore);
% %
% %
% %
-% A c q u i r e V i r t u a l M e m o r y %
+% A c q u i r e Q u a n t u m M e m o r y %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
-% AcquireVirtualMemory() allocates a pointer to a block of memory at least size
-% bytes suitably aligned for any use.
+% AcquireQuantumMemory() returns a pointer to a block of memory at least
+% count * quantum bytes suitably aligned for any use.
%
-% The format of the AcquireVirtualMemory method is:
+% The format of the AcquireQuantumMemory method is:
%
-% MemoryInfo *AcquireVirtualMemory(const size_t count,const size_t quantum)
+% void *AcquireQuantumMemory(const size_t count,const size_t quantum)
%
% A description of each parameter follows:
%
% o quantum: the number of bytes in each quantum.
%
*/
-MagickExport MemoryInfo *AcquireVirtualMemory(const size_t count,
- const size_t quantum)
+MagickExport void *AcquireQuantumMemory(const size_t count,const size_t quantum)
{
- MemoryInfo
- *memory_info;
+ size_t
+ size;
- memory_info=(MemoryInfo *) MagickAssumeAligned(AcquireAlignedMemory(1,
- sizeof(*memory_info)));
- if (memory_info == (MemoryInfo *) NULL)
- ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
- (void) ResetMagickMemory(memory_info,0,sizeof(*memory_info));
- memory_info->signature=MagickSignature;
- return(memory_info);
+ size=count*quantum;
+ if ((count == 0) || (quantum != (size/count)))
+ {
+ errno=ENOMEM;
+ return((void *) NULL);
+ }
+ return(AcquireMagickMemory(size));
}
\f
/*
% %
% %
% %
-% A c q u i r e Q u a n t u m M e m o r y %
+% A c q u i r e V i r t u a l M e m o r y %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
-% AcquireQuantumMemory() returns a pointer to a block of memory at least
-% count * quantum bytes suitably aligned for any use.
+% AcquireVirtualMemory() allocates a pointer to a block of memory at least size
+% bytes suitably aligned for any use.
%
-% The format of the AcquireQuantumMemory method is:
+% The format of the AcquireVirtualMemory method is:
%
-% void *AcquireQuantumMemory(const size_t count,const size_t quantum)
+% MemoryInfo *AcquireVirtualMemory(const size_t count,const size_t quantum)
%
% A description of each parameter follows:
%
% o quantum: the number of bytes in each quantum.
%
*/
-MagickExport void *AcquireQuantumMemory(const size_t count,const size_t quantum)
+MagickExport MemoryInfo *AcquireVirtualMemory(const size_t count,
+ const size_t quantum)
{
+ MemoryInfo
+ *memory_info;
+
size_t
- size;
+ length;
- size=count*quantum;
- if ((count == 0) || (quantum != (size/count)))
+ length=count*quantum;
+ if ((count == 0) || (quantum != (length/count)))
{
errno=ENOMEM;
- return((void *) NULL);
+ return((MemoryInfo *) NULL);
}
- return(AcquireMagickMemory(size));
+ memory_info=(MemoryInfo *) MagickAssumeAligned(AcquireAlignedMemory(1,
+ sizeof(*memory_info)));
+ if (memory_info == (MemoryInfo *) NULL)
+ ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
+ (void) ResetMagickMemory(memory_info,0,sizeof(*memory_info));
+ memory_info->length=length;
+ memory_info->signature=MagickCoreSignature;
+ if (AcquireMagickResource(MemoryResource,length) != MagickFalse)
+ {
+ memory_info->blob=AcquireAlignedMemory(1,length);
+ if (memory_info->blob != NULL)
+ memory_info->type=AlignedVirtualMemory;
+ else
+ RelinquishMagickResource(MemoryResource,length);
+ }
+ if ((memory_info->blob == NULL) &&
+ (AcquireMagickResource(MapResource,length) != MagickFalse))
+ {
+ /*
+ Heap memory failed, try anonymous memory mapping.
+ */
+ memory_info->blob=MapBlob(-1,IOMode,0,length);
+ if (memory_info->blob != NULL)
+ memory_info->type=MapVirtualMemory;
+ else
+ RelinquishMagickResource(MapResource,length);
+ }
+ if ((memory_info->blob == NULL) &&
+ (AcquireMagickResource(DiskResource,length) != MagickFalse))
+ {
+ int
+ file;
+
+ /*
+ Anonymous memory mapping failed, try file-backed memory mapping.
+ */
+ file=AcquireUniqueFileResource(memory_info->filename);
+ if (file == -1)
+ RelinquishMagickResource(DiskResource,length);
+ else
+ {
+ if ((lseek(file,length-1,SEEK_SET) < 0) || (write(file,"",1) != 1))
+ RelinquishMagickResource(DiskResource,length);
+ else
+ {
+ if (AcquireMagickResource(MapResource,length) == MagickFalse)
+ RelinquishMagickResource(DiskResource,length);
+ else
+ {
+ memory_info->blob=MapBlob(file,IOMode,0,length);
+ if (memory_info->blob != NULL)
+ memory_info->type=MapVirtualMemory;
+ else
+ {
+ RelinquishMagickResource(MapResource,length);
+ RelinquishMagickResource(DiskResource,length);
+ }
+ }
+ }
+ (void) close(file);
+ }
+ }
+ if (memory_info->blob == NULL)
+ {
+ memory_info->blob=AcquireMagickMemory(length);
+ if (memory_info->blob != NULL)
+ memory_info->type=UnalignedVirtualMemory;
+ }
+ if (memory_info->blob == NULL)
+ memory_info=RelinquishVirtualMemory(memory_info);
+ return(memory_info);
}
\f
/*
i;
if (memory_semaphore == (SemaphoreInfo *) NULL)
- AcquireSemaphoreInfo(&memory_semaphore);
+ ActivateSemaphoreInfo(&memory_semaphore);
LockSemaphoreInfo(memory_semaphore);
- UnlockSemaphoreInfo(memory_semaphore);
for (i=0; i < (ssize_t) memory_pool.number_segments; i++)
if (memory_pool.segments[i]->mapped == MagickFalse)
memory_methods.destroy_memory_handler(
memory_pool.segments[i]->length);
free_segments=(DataSegmentInfo *) NULL;
(void) ResetMagickMemory(&memory_pool,0,sizeof(memory_pool));
- DestroySemaphoreInfo(&memory_semaphore);
+ UnlockSemaphoreInfo(memory_semaphore);
+ RelinquishSemaphoreInfo(&memory_semaphore);
#endif
}
\f
MagickExport void *GetVirtualMemoryBlob(const MemoryInfo *memory_info)
{
assert(memory_info != (const MemoryInfo *) NULL);
- assert(memory_info->signature == MagickSignature);
+ assert(memory_info->signature == MagickCoreSignature);
return(memory_info->blob);
}
\f
MagickExport MemoryInfo *RelinquishVirtualMemory(MemoryInfo *memory_info)
{
assert(memory_info != (MemoryInfo *) NULL);
- assert(memory_info->signature == MagickSignature);
+ assert(memory_info->signature == MagickCoreSignature);
if (memory_info->blob != (void *) NULL)
- memory_info->blob=(void *) NULL;
- memory_info->signature=(~MagickSignature);
+ switch (memory_info->type)
+ {
+ case AlignedVirtualMemory:
+ {
+ memory_info->blob=RelinquishAlignedMemory(memory_info->blob);
+ RelinquishMagickResource(MemoryResource,memory_info->length);
+ break;
+ }
+ case MapVirtualMemory:
+ {
+ (void) UnmapBlob(memory_info->blob,memory_info->length);
+ memory_info->blob=NULL;
+ RelinquishMagickResource(MapResource,memory_info->length);
+ if (*memory_info->filename != '\0')
+ {
+ (void) RelinquishUniqueFileResource(memory_info->filename);
+ RelinquishMagickResource(DiskResource,memory_info->length);
+ }
+ break;
+ }
+ case UnalignedVirtualMemory:
+ default:
+ {
+ memory_info->blob=RelinquishMagickMemory(memory_info->blob);
+ break;
+ }
+ }
+ memory_info->signature=(~MagickCoreSignature);
memory_info=(MemoryInfo *) RelinquishAlignedMemory(memory_info);
return(memory_info);
}