]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/memory.c
(no commit message)
[imagemagick] / MagickCore / memory.c
index 1a37731012e47e09100f945bcba8edd6ed3697cf..1edb4ad96328af6cfe9e3faf2505183064983c63 100644 (file)
 %                     MagickCore Memory Allocation Methods                    %
 %                                                                             %
 %                              Software Design                                %
-%                                John Cristy                                  %
+%                                   Cristy                                    %
 %                                 July 1998                                   %
 %                                                                             %
 %                                                                             %
-%  Copyright 1999-2013 ImageMagick Studio LLC, a non-profit organization      %
+%  Copyright 1999-2014 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/exception-private.h"
 #include "MagickCore/memory_.h"
 #include "MagickCore/memory-private.h"
+#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
@@ -116,17 +126,23 @@ typedef struct _MagickMemoryMethods
     destroy_memory_handler;
 } MagickMemoryMethods;
 
-typedef struct _MemoryInfo
+struct _MemoryInfo
 {
   char
     filename[MaxTextExtent];
 
-  MagickBooleanType
-    mapped;
+  VirtualMemoryType
+    type;
+
+  size_t
+    length;
 
   void
-    *memory;
-} MemoryInfo;
+    *blob;
+
+  size_t
+    signature;
+};
 
 typedef struct _MemoryPool
 {
@@ -147,14 +163,34 @@ 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;
@@ -427,7 +463,7 @@ MagickExport void *AcquireMagickMemory(const size_t size)
   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);
@@ -469,23 +505,38 @@ MagickExport void *AcquireMagickMemory(const size_t size)
 %                                                                             %
 %                                                                             %
 %                                                                             %
-%   A c q u i r e M e m o r y I n f o                                         %
+%   A c q u i r e Q u a n t u m M e m o r y                                   %
 %                                                                             %
 %                                                                             %
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  AcquireMemoryInfo() returns a MemoryInfo structure.  This method always
-%  succeeds.
+%  AcquireQuantumMemory() returns a pointer to a block of memory at least
+%  count * quantum bytes suitably aligned for any use.
+%
+%  The format of the AcquireQuantumMemory method is:
 %
-%  The format of the AcquireMemoryInfo method is:
+%      void *AcquireQuantumMemory(const size_t count,const size_t quantum)
 %
-%      MemoryInfo *AcquireMemoryInfo(void)
+%  A description of each parameter follows:
+%
+%    o count: the number of quantum elements to allocate.
+%
+%    o quantum: the number of bytes in each quantum.
 %
 */
-MagickExport MemoryInfo *AcquireMemoryInfo(void)
+MagickExport void *AcquireQuantumMemory(const size_t count,const size_t quantum)
 {
-  return((MemoryInfo *) NULL);
+  size_t
+    size;
+
+  size=count*quantum;
+  if ((count == 0) || (quantum != (size/count)))
+    {
+      errno=ENOMEM;
+      return((void *) NULL);
+    }
+  return(AcquireMagickMemory(size));
 }
 \f
 /*
@@ -493,18 +544,18 @@ MagickExport MemoryInfo *AcquireMemoryInfo(void)
 %                                                                             %
 %                                                                             %
 %                                                                             %
-%   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:
 %
@@ -513,18 +564,80 @@ MagickExport MemoryInfo *AcquireMemoryInfo(void)
 %    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=MagickSignature;
+  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)
+    {
+      int
+        file;
+
+      /*
+        Anonymous memory mapping failed, try file-backed memory mapping.
+      */
+      file=AcquireUniqueFileResource(memory_info->filename);
+      if (file != -1)
+        {
+          if ((lseek(file,length-1,SEEK_SET) >= 0) && (write(file,"",1) == 1))
+            {
+              memory_info->blob=MapBlob(file,IOMode,0,length);
+              if (memory_info->blob != NULL)
+                {
+                  memory_info->type=MapVirtualMemory;
+                  (void) AcquireMagickResource(MapResource,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
 /*
@@ -611,7 +724,7 @@ MagickExport void DestroyMagickMemory(void)
     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++)
@@ -623,7 +736,7 @@ MagickExport void DestroyMagickMemory(void)
         memory_pool.segments[i]->length);
   free_segments=(DataSegmentInfo *) NULL;
   (void) ResetMagickMemory(&memory_pool,0,sizeof(memory_pool));
-  DestroySemaphoreInfo(&memory_semaphore);
+  RelinquishSemaphoreInfo(&memory_semaphore);
 #endif
 }
 \f
@@ -750,33 +863,28 @@ MagickExport void GetMagickMemoryMethods(
 %                                                                             %
 %                                                                             %
 %                                                                             %
-%   G e t M e m o r y I n f o M e m o r y                                     %
+%   G e t V i r t u a l M e m o r y B l o b                                   %
 %                                                                             %
 %                                                                             %
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  GetMemoryInfoMemory() returns a pointer to a block of memory at least size
-%  bytes suitably aligned for any use.
+%  GetVirtualMemoryBlob() returns the virtual memory blob associated with the
+%  specified MemoryInfo structure.
 %
-%  The format of the GetMemoryInfoMemory method is:
+%  The format of the GetVirtualMemoryBlob method is:
 %
-%      void *GetMemoryInfoMemory(const MemoryInfo *memory_info,
-%        const size_t count,const size_t quantum)
+%      void *GetVirtualMemoryBlob(const MemoryInfo *memory_info)
 %
 %  A description of each parameter follows:
 %
-%    o memory: A pointer to a block of memory to free for reuse.
-%
-%    o count: the number of quantum elements to allocate.
-%
-%    o quantum: the number of bytes in each quantum.
+%    o memory_info: The MemoryInfo structure.
 */
-MagickExport void *GetMemoryInfoMemory(const MemoryInfo *memory_info,
-  const size_t count,const size_t quantum)
+MagickExport void *GetVirtualMemoryBlob(const MemoryInfo *memory_info)
 {
   assert(memory_info != (const MemoryInfo *) NULL);
-  return(memory_info->memory);
+  assert(memory_info->signature == MagickSignature);
+  return(memory_info->blob);
 }
 \f
 /*
@@ -895,21 +1003,49 @@ MagickExport void *RelinquishMagickMemory(void *memory)
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  RelinquishMemoryInfo() frees memory acquired with AcquireMemoryInfo()
-%  or reuse.
+%  RelinquishVirtualMemory() frees memory acquired with AcquireVirtualMemory().
 %
-%  The format of the RelinquishMemoryInfo method is:
+%  The format of the RelinquishVirtualMemory method is:
 %
-%      void *RelinquishMemoryInfo(const MemoryInfo *memory_info)
+%      MemoryInfo *RelinquishVirtualMemory(MemoryInfo *memory_info)
 %
 %  A description of each parameter follows:
 %
 %    o memory_info: A pointer to a block of memory to free for reuse.
 %
 */
-MagickExport MemoryInfo *RelinquishMemoryInfo(const MemoryInfo *memory_info)
+MagickExport MemoryInfo *RelinquishVirtualMemory(MemoryInfo *memory_info)
 {
-  return((MemoryInfo *) NULL);
+  assert(memory_info != (MemoryInfo *) NULL);
+  assert(memory_info->signature == MagickSignature);
+  if (memory_info->blob != (void *) NULL)
+    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);
+        break;
+      }
+      case UnalignedVirtualMemory:
+      default:
+      {
+        memory_info->blob=RelinquishMagickMemory(memory_info->blob);
+        break;
+      }
+    }
+  memory_info->signature=(~MagickSignature);
+  memory_info=(MemoryInfo *) RelinquishAlignedMemory(memory_info);
+  return(memory_info);
 }
 \f
 /*