]> granicus.if.org Git - imagemagick/blobdiff - MagickCore/cache.c
(no commit message)
[imagemagick] / MagickCore / cache.c
index ce763488f2254ef80c2a3b85930b7afb4925112e..204f129f03ed9f1dddf050e671bd168ca9c14c09 100644 (file)
 %                       MagickCore Pixel Cache Methods                        %
 %                                                                             %
 %                              Software Design                                %
-%                                John Cristy                                  %
+%                                   Cristy                                    %
 %                                 July 1999                                   %
 %                                                                             %
 %                                                                             %
-%  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  %
@@ -171,7 +171,7 @@ static SemaphoreInfo
 MagickPrivate Cache AcquirePixelCache(const size_t number_threads)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   char
     *synchronize;
@@ -201,9 +201,9 @@ MagickPrivate Cache AcquirePixelCache(const size_t number_threads)
       cache_info->synchronize=IsStringTrue(synchronize);
       synchronize=DestroyString(synchronize);
     }
-  cache_info->semaphore=AllocateSemaphoreInfo();
+  cache_info->semaphore=AcquireSemaphoreInfo();
   cache_info->reference_count=1;
-  cache_info->file_semaphore=AllocateSemaphoreInfo();
+  cache_info->file_semaphore=AcquireSemaphoreInfo();
   cache_info->debug=IsEventLogging();
   cache_info->signature=MagickSignature;
   return((Cache ) cache_info);
@@ -234,7 +234,7 @@ MagickPrivate Cache AcquirePixelCache(const size_t number_threads)
 MagickPrivate NexusInfo **AcquirePixelCacheNexus(const size_t number_threads)
 {
   NexusInfo
-    **nexus_info;
+    **restrict nexus_info;
 
   register ssize_t
     i;
@@ -288,7 +288,7 @@ MagickPrivate const void *AcquirePixelCachePixels(const Image *image,
   MagickSizeType *length,ExceptionInfo *exception)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   assert(image != (const Image *) NULL);
   assert(image->signature == MagickSignature);
@@ -324,7 +324,8 @@ MagickPrivate const void *AcquirePixelCachePixels(const Image *image,
 */
 MagickPrivate MagickBooleanType CacheComponentGenesis(void)
 {
-  AcquireSemaphoreInfo(&cache_semaphore);
+  if (cache_semaphore == (SemaphoreInfo *) NULL)
+    cache_semaphore=AcquireSemaphoreInfo();
   return(MagickTrue);
 }
 \f
@@ -349,11 +350,11 @@ MagickPrivate MagickBooleanType CacheComponentGenesis(void)
 MagickPrivate void CacheComponentTerminus(void)
 {
   if (cache_semaphore == (SemaphoreInfo *) NULL)
-    AcquireSemaphoreInfo(&cache_semaphore);
+    ActivateSemaphoreInfo(&cache_semaphore);
   LockSemaphoreInfo(cache_semaphore);
   instantiate_cache=MagickFalse;
   UnlockSemaphoreInfo(cache_semaphore);
-  DestroySemaphoreInfo(&cache_semaphore);
+  RelinquishSemaphoreInfo(&cache_semaphore);
 }
 \f
 /*
@@ -381,10 +382,10 @@ MagickPrivate void CacheComponentTerminus(void)
 MagickPrivate Cache ClonePixelCache(const Cache cache)
 {
   CacheInfo
-    *clone_info;
+    *restrict clone_info;
 
   const CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   assert(cache != NULL);
   cache_info=(const CacheInfo *) cache;
@@ -427,8 +428,8 @@ MagickPrivate Cache ClonePixelCache(const Cache cache)
 MagickPrivate void ClonePixelCacheMethods(Cache clone,const Cache cache)
 {
   CacheInfo
-    *cache_info,
-    *source_info;
+    *restrict cache_info,
+    *restrict source_info;
 
   assert(clone != (Cache) NULL);
   source_info=(CacheInfo *) clone;
@@ -470,6 +471,29 @@ MagickPrivate void ClonePixelCacheMethods(Cache clone,const Cache cache)
 %
 */
 
+static inline void CopyPixels(Quantum *destination,const Quantum *source,
+  const MagickSizeType number_pixels)
+{
+#if !defined(MAGICKCORE_OPENMP_SUPPORT) || (MAGICKCORE_QUANTUM_DEPTH <= 8)
+  (void) memcpy(destination,source,(size_t) number_pixels*sizeof(*source));
+#else
+  {
+    register MagickOffsetType
+      i;
+
+    if ((number_pixels*sizeof(*source)) < MagickMaxBufferExtent)
+      {
+        (void) memcpy(destination,source,(size_t) number_pixels*
+          sizeof(*source));
+        return;
+      }
+    #pragma omp parallel for
+    for (i=0; i < (MagickOffsetType) number_pixels; i++)
+      destination[i]=source[i];
+  }
+#endif
+}
+
 static inline MagickSizeType MagickMin(const MagickSizeType x,
   const MagickSizeType y)
 {
@@ -478,8 +502,9 @@ static inline MagickSizeType MagickMin(const MagickSizeType x,
   return(y);
 }
 
-static MagickBooleanType ClonePixelCacheRepository(CacheInfo *clone_info,
-  CacheInfo *cache_info,ExceptionInfo *exception)
+static MagickBooleanType ClonePixelCacheRepository(
+  CacheInfo *restrict clone_info,CacheInfo *restrict cache_info,
+  ExceptionInfo *exception)
 {
 #define MaxCacheThreads  2
 #define cache_threads(source,destination,chunk) \
@@ -492,8 +517,8 @@ static MagickBooleanType ClonePixelCacheRepository(CacheInfo *clone_info,
     status;
 
   NexusInfo
-    **cache_nexus,
-    **clone_nexus;
+    **restrict cache_nexus,
+    **restrict clone_nexus;
 
   size_t
     length;
@@ -515,12 +540,8 @@ static MagickBooleanType ClonePixelCacheRepository(CacheInfo *clone_info,
       (memcmp(cache_info->channel_map,clone_info->channel_map,length) == 0) &&
       (cache_info->metacontent_extent == clone_info->metacontent_extent))
     {
-      /*
-        Identical pixel cache morphology.
-      */
-      (void) memcpy(clone_info->pixels,cache_info->pixels,cache_info->columns*
-        cache_info->number_channels*cache_info->rows*
-        sizeof(*cache_info->pixels));
+      CopyPixels(clone_info->pixels,cache_info->pixels,cache_info->columns*
+        cache_info->number_channels*cache_info->rows);
       if (cache_info->metacontent_extent != 0)
         (void) memcpy(clone_info->metacontent,cache_info->metacontent,
           cache_info->columns*cache_info->rows*clone_info->metacontent_extent*
@@ -580,6 +601,7 @@ static MagickBooleanType ClonePixelCacheRepository(CacheInfo *clone_info,
       clone_nexus[id],exception);
     if (pixels == (Quantum *) NULL)
       continue;
+    (void) ResetMagickMemory(clone_nexus[id]->pixels,0,clone_nexus[id]->length);
     if (optimize != MagickFalse)
       (void) memcpy(clone_nexus[id]->pixels,cache_nexus[id]->pixels,length*
         sizeof(Quantum));
@@ -666,8 +688,10 @@ static MagickBooleanType ClonePixelCacheRepository(CacheInfo *clone_info,
           clone_nexus[id],exception);
         if (pixels == (Quantum *) NULL)
           continue;
-        (void) memcpy(clone_nexus[id]->metacontent,cache_nexus[id]->metacontent,
-          length*sizeof(cache_nexus[id]->metacontent));
+        if (clone_nexus[id]->metacontent != (void *) NULL)
+          (void) memcpy(clone_nexus[id]->metacontent,
+            cache_nexus[id]->metacontent,length*
+            sizeof(cache_nexus[id]->metacontent));
         status=WritePixelCacheMetacontent(clone_info,clone_nexus[id],exception);
       }
     }
@@ -744,7 +768,7 @@ static void DestroyImagePixelCache(Image *image)
 MagickExport void DestroyImagePixels(Image *image)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   assert(image != (const Image *) NULL);
   assert(image->signature == MagickSignature);
@@ -809,15 +833,17 @@ static inline void RelinquishPixelCachePixels(CacheInfo *cache_info)
         cache_info->pixels=(Quantum *) RelinquishAlignedMemory(
           cache_info->pixels);
       else
-        cache_info->pixels=(Quantum *) UnmapBlob(cache_info->pixels,
-          (size_t) cache_info->length);
+        {
+          (void) UnmapBlob(cache_info->pixels,(size_t) cache_info->length);
+          cache_info->pixels=(Quantum *) NULL;
+        }
       RelinquishMagickResource(MemoryResource,cache_info->length);
       break;
     }
     case MapCache:
     {
-      cache_info->pixels=(Quantum *) UnmapBlob(cache_info->pixels,(size_t)
-        cache_info->length);
+      (void) UnmapBlob(cache_info->pixels,(size_t) cache_info->length);
+      cache_info->pixels=(Quantum *) NULL;
       if (cache_info->mode != ReadMode)
         (void) RelinquishUniqueFileResource(cache_info->cache_filename);
       *cache_info->cache_filename='\0';
@@ -851,7 +877,7 @@ static inline void RelinquishPixelCachePixels(CacheInfo *cache_info)
 MagickPrivate Cache DestroyPixelCache(Cache cache)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   assert(cache != (Cache) NULL);
   cache_info=(CacheInfo *) cache;
@@ -886,9 +912,9 @@ MagickPrivate Cache DestroyPixelCache(Cache cache)
   if (cache_info->random_info != (RandomInfo *) NULL)
     cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
   if (cache_info->file_semaphore != (SemaphoreInfo *) NULL)
-    DestroySemaphoreInfo(&cache_info->file_semaphore);
+    RelinquishSemaphoreInfo(&cache_info->file_semaphore);
   if (cache_info->semaphore != (SemaphoreInfo *) NULL)
-    DestroySemaphoreInfo(&cache_info->semaphore);
+    RelinquishSemaphoreInfo(&cache_info->semaphore);
   cache_info->signature=(~MagickSignature);
   cache_info=(CacheInfo *) RelinquishMagickMemory(cache_info);
   cache=(Cache) NULL;
@@ -979,7 +1005,7 @@ MagickPrivate NexusInfo **DestroyPixelCacheNexus(NexusInfo **nexus_info,
 MagickExport void *GetAuthenticMetacontent(const Image *image)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
@@ -1030,7 +1056,7 @@ MagickExport void *GetAuthenticMetacontent(const Image *image)
 static void *GetAuthenticMetacontentFromCache(const Image *image)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
@@ -1084,10 +1110,10 @@ MagickPrivate Quantum *GetAuthenticPixelCacheNexus(Image *image,const ssize_t x,
   ExceptionInfo *exception)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   Quantum
-    *pixels;
+    *restrict pixels;
 
   /*
     Transfer pixels from the cache.
@@ -1100,7 +1126,7 @@ MagickPrivate Quantum *GetAuthenticPixelCacheNexus(Image *image,const ssize_t x,
     return((Quantum *) NULL);
   cache_info=(CacheInfo *) image->cache;
   assert(cache_info->signature == MagickSignature);
-  if (nexus_info->authentic_cache != MagickFalse)
+  if (nexus_info->authentic_pixel_cache != MagickFalse)
     return(pixels);
   if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
     return((Quantum *) NULL);
@@ -1136,7 +1162,7 @@ MagickPrivate Quantum *GetAuthenticPixelCacheNexus(Image *image,const ssize_t x,
 static Quantum *GetAuthenticPixelsFromCache(const Image *image)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
@@ -1177,7 +1203,7 @@ static Quantum *GetAuthenticPixelsFromCache(const Image *image)
 MagickExport Quantum *GetAuthenticPixelQueue(const Image *image)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
@@ -1243,7 +1269,7 @@ MagickExport Quantum *GetAuthenticPixels(Image *image,const ssize_t x,
   ExceptionInfo *exception)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
@@ -1305,13 +1331,13 @@ static Quantum *GetAuthenticPixelsCache(Image *image,const ssize_t x,
   ExceptionInfo *exception)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
 
   Quantum
-    *pixels;
+    *restrict pixels;
 
   assert(image != (const Image *) NULL);
   assert(image->signature == MagickSignature);
@@ -1352,7 +1378,7 @@ static Quantum *GetAuthenticPixelsCache(Image *image,const ssize_t x,
 MagickExport MagickSizeType GetImageExtent(const Image *image)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
@@ -1433,7 +1459,7 @@ static Cache GetImagePixelCache(Image *image,const MagickBooleanType clone,
   ExceptionInfo *exception)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   MagickBooleanType
     destroy,
@@ -1463,7 +1489,12 @@ static Cache GetImagePixelCache(Image *image,const MagickBooleanType clone,
     }
   if ((time_limit != MagickResourceInfinity) &&
       ((MagickSizeType) (time((time_t *) NULL)-cache_timestamp) >= time_limit))
-    ThrowFatalException(ResourceLimitFatalError,"TimeLimitExceeded");
+     {
+#if defined(ECANCELED)
+       errno=ECANCELED;
+#endif
+       ThrowFatalException(ResourceLimitFatalError,"TimeLimitExceeded");
+     }
   assert(image->cache != (Cache) NULL);
   cache_info=(CacheInfo *) image->cache;
   destroy=MagickFalse;
@@ -1482,7 +1513,7 @@ static Cache GetImagePixelCache(Image *image,const MagickBooleanType clone,
             Clone pixel cache.
           */
           clone_image=(*image);
-          clone_image.semaphore=AllocateSemaphoreInfo();
+          clone_image.semaphore=AcquireSemaphoreInfo();
           clone_image.reference_count=1;
           clone_image.cache=ClonePixelCache(cache_info);
           clone_info=(CacheInfo *) clone_image.cache;
@@ -1500,7 +1531,7 @@ static Cache GetImagePixelCache(Image *image,const MagickBooleanType clone,
                   image->cache=clone_image.cache;
                 }
             }
-          DestroySemaphoreInfo(&clone_image.semaphore);
+          RelinquishSemaphoreInfo(&clone_image.semaphore);
         }
       UnlockSemaphoreInfo(cache_info->semaphore);
     }
@@ -1553,7 +1584,7 @@ static Cache GetImagePixelCache(Image *image,const MagickBooleanType clone,
 MagickExport CacheType GetImagePixelCacheType(const Image *image)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   assert(image != (Image *) NULL);
   assert(image->signature == MagickSignature);
@@ -1597,7 +1628,7 @@ MagickExport MagickBooleanType GetOneAuthenticPixel(Image *image,
   const ssize_t x,const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   register Quantum
     *restrict q;
@@ -1668,7 +1699,7 @@ static MagickBooleanType GetOneAuthenticPixelFromCache(Image *image,
   const ssize_t x,const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
@@ -1740,7 +1771,7 @@ MagickExport MagickBooleanType GetOneVirtualPixel(const Image *image,
   const ssize_t x,const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
@@ -1820,7 +1851,7 @@ static MagickBooleanType GetOneVirtualPixelFromCache(const Image *image,
   Quantum *pixel,ExceptionInfo *exception)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
@@ -1896,13 +1927,13 @@ MagickExport MagickBooleanType GetOneVirtualPixelInfo(const Image *image,
   PixelInfo *pixel,ExceptionInfo *exception)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
 
   register const Quantum
-    *p;
+    *restrict p;
 
   assert(image != (const Image *) NULL);
   assert(image->signature == MagickSignature);
@@ -1944,7 +1975,7 @@ MagickExport MagickBooleanType GetOneVirtualPixelInfo(const Image *image,
 MagickPrivate ColorspaceType GetPixelCacheColorspace(const Cache cache)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   assert(cache != (Cache) NULL);
   cache_info=(CacheInfo *) cache;
@@ -2023,10 +2054,10 @@ MagickPrivate void GetPixelCacheMethods(CacheMethods *cache_methods)
 %
 */
 MagickPrivate MagickSizeType GetPixelCacheNexusExtent(const Cache cache,
-  NexusInfo *nexus_info)
+  NexusInfo *restrict nexus_info)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   MagickSizeType
     extent;
@@ -2071,7 +2102,7 @@ MagickPrivate void *GetPixelCachePixels(Image *image,MagickSizeType *length,
   ExceptionInfo *exception)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   assert(image != (const Image *) NULL);
   assert(image->signature == MagickSignature);
@@ -2115,7 +2146,7 @@ MagickPrivate void *GetPixelCachePixels(Image *image,MagickSizeType *length,
 MagickPrivate ClassType GetPixelCacheStorageClass(const Cache cache)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   assert(cache != (Cache) NULL);
   cache_info=(CacheInfo *) cache;
@@ -2157,7 +2188,7 @@ MagickPrivate void GetPixelCacheTileSize(const Image *image,size_t *width,
   size_t *height)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   assert(image != (Image *) NULL);
   assert(image->signature == MagickSignature);
@@ -2198,7 +2229,7 @@ MagickPrivate void GetPixelCacheTileSize(const Image *image,size_t *width,
 MagickPrivate VirtualPixelMethod GetPixelCacheVirtualMethod(const Image *image)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   assert(image != (Image *) NULL);
   assert(image->signature == MagickSignature);
@@ -2234,13 +2265,13 @@ MagickPrivate VirtualPixelMethod GetPixelCacheVirtualMethod(const Image *image)
 static const void *GetVirtualMetacontentFromCache(const Image *image)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
 
   const void
-    *metacontent;
+    *restrict metacontent;
 
   assert(image != (const Image *) NULL);
   assert(image->signature == MagickSignature);
@@ -2280,10 +2311,10 @@ static const void *GetVirtualMetacontentFromCache(const Image *image)
 %
 */
 MagickPrivate const void *GetVirtualMetacontentFromNexus(const Cache cache,
-  NexusInfo *nexus_info)
+  NexusInfo *restrict nexus_info)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   assert(cache != (Cache) NULL);
   cache_info=(CacheInfo *) cache;
@@ -2320,13 +2351,13 @@ MagickPrivate const void *GetVirtualMetacontentFromNexus(const Cache cache,
 MagickExport const void *GetVirtualMetacontent(const Image *image)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
 
   const void
-    *metacontent;
+    *restrict metacontent;
 
   assert(image != (const Image *) NULL);
   assert(image->signature == MagickSignature);
@@ -2472,7 +2503,7 @@ MagickPrivate const Quantum *GetVirtualPixelsFromNexus(const Image *image,
   ExceptionInfo *exception)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   MagickOffsetType
     offset;
@@ -2482,10 +2513,10 @@ MagickPrivate const Quantum *GetVirtualPixelsFromNexus(const Image *image,
     number_pixels;
 
   NexusInfo
-    **virtual_nexus;
+    **restrict virtual_nexus;
 
   Quantum
-    *pixels,
+    *restrict pixels,
     virtual_pixel[MaxPixelChannels];
 
   RectangleInfo
@@ -2511,7 +2542,7 @@ MagickPrivate const Quantum *GetVirtualPixelsFromNexus(const Image *image,
     v;
 
   void
-    *virtual_metacontent;
+    *restrict virtual_metacontent;
 
   /*
     Acquire pixels.
@@ -2547,7 +2578,7 @@ MagickPrivate const Quantum *GetVirtualPixelsFromNexus(const Image *image,
         /*
           Pixel request is inside cache extents.
         */
-        if (nexus_info->authentic_cache != MagickFalse)
+        if (nexus_info->authentic_pixel_cache != MagickFalse)
           return(q);
         status=ReadPixelCachePixels(cache_info,nexus_info,exception);
         if (status == MagickFalse)
@@ -2899,13 +2930,13 @@ static const Quantum *GetVirtualPixelCache(const Image *image,
   const size_t columns,const size_t rows,ExceptionInfo *exception)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
 
   const Quantum
-    *p;
+    *restrict p;
 
   assert(image != (const Image *) NULL);
   assert(image->signature == MagickSignature);
@@ -2944,7 +2975,7 @@ static const Quantum *GetVirtualPixelCache(const Image *image,
 MagickExport const Quantum *GetVirtualPixelQueue(const Image *image)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
@@ -3014,13 +3045,13 @@ MagickExport const Quantum *GetVirtualPixels(const Image *image,
   ExceptionInfo *exception)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
 
   const Quantum
-    *p;
+    *restrict p;
 
   assert(image != (const Image *) NULL);
   assert(image->signature == MagickSignature);
@@ -3063,7 +3094,7 @@ MagickExport const Quantum *GetVirtualPixels(const Image *image,
 static const Quantum *GetVirtualPixelsCache(const Image *image)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
@@ -3104,10 +3135,10 @@ static const Quantum *GetVirtualPixelsCache(const Image *image)
 %
 */
 MagickPrivate const Quantum *GetVirtualPixelsNexus(const Cache cache,
-  NexusInfo *nexus_info)
+  NexusInfo *restrict nexus_info)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   assert(cache != (Cache) NULL);
   cache_info=(CacheInfo *) cache;
@@ -3161,6 +3192,21 @@ static inline void AllocatePixelCachePixels(CacheInfo *cache_info)
     }
 }
 
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#if defined(SIGBUS)
+static void CacheSignalHandler(int status)
+{
+  ThrowFatalException(CacheFatalError,"UnableToExtendPixelCache");
+}
+#endif
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
 static MagickBooleanType OpenPixelCacheOnDisk(CacheInfo *cache_info,
   const MapMode mode)
 {
@@ -3245,7 +3291,7 @@ static inline MagickOffsetType WritePixelCacheRegion(
 static MagickBooleanType SetPixelCacheExtent(Image *image,MagickSizeType length)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   MagickOffsetType
     count,
@@ -3284,6 +3330,9 @@ static MagickBooleanType SetPixelCacheExtent(Image *image,MagickSizeType length)
       if (status != 0)
         return(MagickFalse);
     }
+#endif
+#if defined(SIGBUS)
+  (void) signal(SIGBUS,CacheSignalHandler);
 #endif
   return(count != (MagickOffsetType) 1 ? MagickFalse : MagickTrue);
 }
@@ -3292,7 +3341,7 @@ static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
   ExceptionInfo *exception)
 {
   CacheInfo
-    *cache_info,
+    *restrict cache_info,
     source_info;
 
   char
@@ -3465,6 +3514,7 @@ static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
               return(MagickTrue);
             }
         }
+      RelinquishMagickResource(DiskResource,cache_info->length);
       (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
         "CacheResourcesExhausted","`%s'",image->filename);
       return(MagickFalse);
@@ -3610,8 +3660,8 @@ MagickExport MagickBooleanType PersistPixelCache(Image *image,
   ExceptionInfo *exception)
 {
   CacheInfo
-    *cache_info,
-    *clone_info;
+    *restrict cache_info,
+    *restrict clone_info;
 
   Image
     clone_image;
@@ -3743,7 +3793,7 @@ MagickPrivate Quantum *QueueAuthenticPixelCacheNexus(Image *image,
   const MagickBooleanType clone,NexusInfo *nexus_info,ExceptionInfo *exception)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   MagickOffsetType
     offset;
@@ -3752,7 +3802,7 @@ MagickPrivate Quantum *QueueAuthenticPixelCacheNexus(Image *image,
     number_pixels;
 
   Quantum
-    *pixels;
+    *restrict pixels;
 
   RectangleInfo
     region;
@@ -3832,13 +3882,13 @@ static Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
   ExceptionInfo *exception)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
 
   Quantum
-    *pixels;
+    *restrict pixels;
 
   assert(image != (const Image *) NULL);
   assert(image->signature == MagickSignature);
@@ -3912,13 +3962,13 @@ MagickExport Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
   ExceptionInfo *exception)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
 
   Quantum
-    *pixels;
+    *restrict pixels;
 
   assert(image != (Image *) NULL);
   assert(image->signature == MagickSignature);
@@ -4001,8 +4051,9 @@ static inline MagickOffsetType ReadPixelCacheRegion(
   return(i);
 }
 
-static MagickBooleanType ReadPixelCacheMetacontent(CacheInfo *cache_info,
-  NexusInfo *nexus_info,ExceptionInfo *exception)
+static MagickBooleanType ReadPixelCacheMetacontent(
+  CacheInfo *restrict cache_info,NexusInfo *restrict nexus_info,
+  ExceptionInfo *exception)
 {
   MagickOffsetType
     count,
@@ -4023,7 +4074,7 @@ static MagickBooleanType ReadPixelCacheMetacontent(CacheInfo *cache_info,
 
   if (cache_info->metacontent_extent == 0)
     return(MagickFalse);
-  if (nexus_info->authentic_cache != MagickFalse)
+  if (nexus_info->authentic_pixel_cache != MagickFalse)
     return(MagickTrue);
   offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
     nexus_info->region.x;
@@ -4171,8 +4222,8 @@ static MagickBooleanType ReadPixelCacheMetacontent(CacheInfo *cache_info,
 %    o exception: return any errors or warnings in this structure.
 %
 */
-static MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
-  NexusInfo *nexus_info,ExceptionInfo *exception)
+static MagickBooleanType ReadPixelCachePixels(CacheInfo *restrict cache_info,
+  NexusInfo *restrict nexus_info,ExceptionInfo *exception)
 {
   MagickOffsetType
     count,
@@ -4191,7 +4242,7 @@ static MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
   size_t
     rows;
 
-  if (nexus_info->authentic_cache != MagickFalse)
+  if (nexus_info->authentic_pixel_cache != MagickFalse)
     return(MagickTrue);
   offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
     nexus_info->region.x;
@@ -4334,7 +4385,7 @@ static MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
 MagickPrivate Cache ReferencePixelCache(Cache cache)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   assert(cache != (Cache *) NULL);
   cache_info=(CacheInfo *) cache;
@@ -4372,7 +4423,7 @@ MagickPrivate Cache ReferencePixelCache(Cache cache)
 MagickPrivate void SetPixelCacheMethods(Cache cache,CacheMethods *cache_methods)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   GetOneAuthenticPixelFromHandler
     get_one_authentic_pixel_from_handler;
@@ -4494,6 +4545,27 @@ static inline MagickBooleanType AcquireCacheNexusPixels(
   return(MagickTrue);
 }
 
+static inline MagickBooleanType IsPixelCacheAuthentic(
+  const CacheInfo *restrict cache_info,const NexusInfo *restrict nexus_info)
+{
+  MagickBooleanType
+    status;
+
+  MagickOffsetType
+    offset;
+
+  /*
+    Does nexus pixels point directly to in-core cache pixels or is it buffered?
+  */
+  if (cache_info->type == PingCache)
+    return(MagickTrue);
+  offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
+    nexus_info->region.x;
+  status=nexus_info->pixels == (cache_info->pixels+offset*
+    cache_info->number_channels) ? MagickTrue : MagickFalse;
+  return(status);
+}
+
 static inline void PrefetchPixelCacheNexusPixels(const NexusInfo *nexus_info,
   const MapMode mode)
 {
@@ -4541,7 +4613,6 @@ static Quantum *SetPixelCacheNexusPixels(const CacheInfo *cache_info,
           /*
             Pixels are accessed directly from memory.
           */
-          nexus_info->authentic_cache=MagickTrue;
           offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
             nexus_info->region.x;
           nexus_info->pixels=cache_info->pixels+cache_info->number_channels*
@@ -4551,13 +4622,14 @@ static Quantum *SetPixelCacheNexusPixels(const CacheInfo *cache_info,
             nexus_info->metacontent=(unsigned char *) cache_info->metacontent+
               offset*cache_info->metacontent_extent;
           PrefetchPixelCacheNexusPixels(nexus_info,mode);
+          nexus_info->authentic_pixel_cache=IsPixelCacheAuthentic(cache_info,
+            nexus_info);
           return(nexus_info->pixels);
         }
     }
   /*
     Pixels are stored in a staging region until they are synced to the cache.
   */
-  nexus_info->authentic_cache=MagickFalse;
   number_pixels=(MagickSizeType) nexus_info->region.width*
     nexus_info->region.height;
   length=number_pixels*cache_info->number_channels*sizeof(Quantum);
@@ -4591,6 +4663,8 @@ static Quantum *SetPixelCacheNexusPixels(const CacheInfo *cache_info,
     nexus_info->metacontent=(void *) (nexus_info->pixels+number_pixels*
       cache_info->number_channels);
   PrefetchPixelCacheNexusPixels(nexus_info,mode);
+  nexus_info->authentic_pixel_cache=IsPixelCacheAuthentic(cache_info,
+    nexus_info);
   return(nexus_info->pixels);
 }
 \f
@@ -4628,10 +4702,10 @@ static MagickBooleanType SetCacheAlphaChannel(Image *image,const Quantum alpha,
   ExceptionInfo *exception)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   CacheView
-    *image_view;
+    *restrict image_view;
 
   MagickBooleanType
     status;
@@ -4684,7 +4758,7 @@ MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(Image *image,
   const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   VirtualPixelMethod
     method;
@@ -4753,10 +4827,10 @@ MagickPrivate VirtualPixelMethod SetPixelCacheVirtualMethod(Image *image,
 %
 */
 MagickPrivate MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
-  NexusInfo *nexus_info,ExceptionInfo *exception)
+  NexusInfo *restrict nexus_info,ExceptionInfo *exception)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   MagickBooleanType
     status;
@@ -4772,7 +4846,7 @@ MagickPrivate MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
   assert(cache_info->signature == MagickSignature);
   if (cache_info->type == UndefinedCache)
     return(MagickFalse);
-  if (nexus_info->authentic_cache != MagickFalse)
+  if (nexus_info->authentic_pixel_cache != MagickFalse)
     return(MagickTrue);
   assert(cache_info->signature == MagickSignature);
   status=WritePixelCachePixels(cache_info,nexus_info,exception);
@@ -4813,7 +4887,7 @@ static MagickBooleanType SyncAuthenticPixelsCache(Image *image,
   ExceptionInfo *exception)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
@@ -4863,7 +4937,7 @@ MagickExport MagickBooleanType SyncAuthenticPixels(Image *image,
   ExceptionInfo *exception)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   const int
     id = GetOpenMPThreadId();
@@ -4920,7 +4994,7 @@ MagickPrivate MagickBooleanType SyncImagePixelCache(Image *image,
   ExceptionInfo *exception)
 {
   CacheInfo
-    *cache_info;
+    *restrict cache_info;
 
   assert(image != (Image *) NULL);
   assert(exception != (ExceptionInfo *) NULL);
@@ -4957,7 +5031,7 @@ MagickPrivate MagickBooleanType SyncImagePixelCache(Image *image,
 %
 */
 static MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
-  NexusInfo *nexus_info,ExceptionInfo *exception)
+  NexusInfo *restrict nexus_info,ExceptionInfo *exception)
 {
   MagickOffsetType
     count,
@@ -4978,7 +5052,7 @@ static MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
 
   if (cache_info->metacontent_extent == 0)
     return(MagickFalse);
-  if (nexus_info->authentic_cache != MagickFalse)
+  if (nexus_info->authentic_pixel_cache != MagickFalse)
     return(MagickTrue);
   offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
     nexus_info->region.x;
@@ -5126,8 +5200,8 @@ static MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
 %    o exception: return any errors or warnings in this structure.
 %
 */
-static MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
-  NexusInfo *nexus_info,ExceptionInfo *exception)
+static MagickBooleanType WritePixelCachePixels(CacheInfo *restrict cache_info,
+  NexusInfo *restrict nexus_info,ExceptionInfo *exception)
 {
   MagickOffsetType
     count,
@@ -5146,7 +5220,7 @@ static MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
   size_t
     rows;
 
-  if (nexus_info->authentic_cache != MagickFalse)
+  if (nexus_info->authentic_pixel_cache != MagickFalse)
     return(MagickTrue);
   offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
     nexus_info->region.x;