If Ashmem cache fails pinCache, do not reallocate.
authorscroggo@google.com <scroggo@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Mon, 4 Mar 2013 21:38:50 +0000 (21:38 +0000)
committerscroggo@google.com <scroggo@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Mon, 4 Mar 2013 21:38:50 +0000 (21:38 +0000)
Review URL: https://codereview.chromium.org/12398021

git-svn-id: http://skia.googlecode.com/svn/trunk@7973 2bbb7eff-a529-9590-31e7-b0007b416f81

include/lazy/SkImageCache.h
src/lazy/SkLazyPixelRef.cpp
src/lazy/SkLruImageCache.cpp
src/ports/SkAshmemImageCache.cpp

index 045ce2c384f168c94129408d65b67ffaa6274d14..6cd064ba5bfae6cd73672975080cf4d5d82ef318 100644 (file)
@@ -34,15 +34,16 @@ public:
      *  @param ID Unique ID for the memory block.
      *  @return Pointer: If non-NULL, points to the previously allocated memory, in which case
      *          this call must be balanced with a call to releaseCache. If NULL, the memory
-     *          has been reclaimed, so allocAndPinCache must be called again, and ID is no
-     *          longer valid (thus throwAwayCache need not be called).
+     *          has been reclaimed, so allocAndPinCache must be called again with a pointer to
+     *          the same ID.
      */
     virtual void* pinCache(intptr_t ID) = 0;
 
     /**
      *  Inform the cache that it is safe to free the block of memory corresponding to ID. After
-     *  calling this function, the pointer returnted by allocAndPinCache or pinCache must not be
-     *  used again. In order to access the same memory after this, pinCache must be called.
+     *  calling this function, the pointer returned by allocAndPinCache or pinCache must not be
+     *  used again. In order to access the same memory after this, pinCache must be called with
+     *  the same ID.
      *  @param ID Unique ID for the memory block which is now safe to age out of the cache.
      */
     virtual void releaseCache(intptr_t ID) = 0;
@@ -50,8 +51,7 @@ public:
     /**
      *  Inform the cache that the block of memory associated with ID will not be asked for again.
      *  After this call, ID is no longer valid. Must not be called while the associated memory is
-     *  pinned. Must be called to balance a successful allocAndPinCache, unless a later pinCache
-     *  returns NULL.
+     *  pinned. Must be called to balance a successful allocAndPinCache.
      */
     virtual void throwAwayCache(intptr_t ID) = 0;
 
index a20b3c028d0850cd80075b01225422bf30007c74..9ae22f22075d5dab30f55e931e761a16759cb6e2 100644 (file)
@@ -88,6 +88,8 @@ void* SkLazyPixelRef::onLockPixels(SkColorTable**) {
     // FIXME: As an optimization, only do this part once.
     fErrorInDecoding = !fDecodeProc(fData->data(), fData->size(), &info, NULL);
     if (fErrorInDecoding) {
+        // In case a previous call to allocAndPinCache succeeded.
+        fImageCache->throwAwayCache(fCacheId);
         fCacheId = SkImageCache::UNINITIALIZED_ID;
         return NULL;
     }
index 6beb8a479bf59497b9ead4802aca899252ea58d6..54f26fb5dcbf8263e143b12ce9efe846b5f1da38 100644 (file)
@@ -133,7 +133,6 @@ void SkLruImageCache::releaseCache(intptr_t ID) {
 }
 
 void SkLruImageCache::throwAwayCache(intptr_t ID) {
-    SkASSERT(ID != SkImageCache::UNINITIALIZED_ID);
     SkAutoMutexAcquire ac(&fMutex);
     CachedPixels* pixels = this->findByID(ID);
     if (pixels != NULL) {
@@ -156,6 +155,9 @@ void SkLruImageCache::removePixels(CachedPixels* pixels) {
 
 CachedPixels* SkLruImageCache::findByID(intptr_t ID) const {
     // Mutex is already locked.
+    if (SkImageCache::UNINITIALIZED_ID == ID) {
+        return NULL;
+    }
     Iter iter;
     // Start from the head, most recently used.
     CachedPixels* pixels = iter.init(fLRU, Iter::kHead_IterStart);
index a85542271df733e5c2a421f62e4ef9c69a38008e..b7c6c7058b7d23f96c87b5bed293a6f985a8f4ca 100644 (file)
@@ -41,11 +41,26 @@ static size_t roundToPageSize(size_t size) {
 }
 
 void* SkAshmemImageCache::allocAndPinCache(size_t bytes, intptr_t* ID) {
-    AshmemRec rec;
-    rec.fSize = roundToPageSize(bytes);
+    SkASSERT(ID != NULL);
 
     SkAutoMutexAcquire ac(&gAshmemMutex);
 
+    if (*ID != SkImageCache::UNINITIALIZED_ID) {
+        // This rec was previously allocated, but pinCache subsequently
+        // failed.
+        AshmemRec* pRec = reinterpret_cast<AshmemRec*>(*ID);
+        SkASSERT(roundToPageSize(bytes) == pRec->fSize);
+        SkASSERT(pRec->fFD != -1);
+        (void) ashmem_pin_region(pRec->fFD, 0, 0);
+#ifdef SK_DEBUG
+        pRec->fPinned = true;
+#endif
+        return pRec->fAddr;
+    }
+
+    AshmemRec rec;
+    rec.fSize = roundToPageSize(bytes);
+
     rec.fFD = ashmem_create_region(NULL, rec.fSize);
     if (-1 == rec.fFD) {
         SkDebugf("ashmem_create_region failed\n");
@@ -70,7 +85,6 @@ void* SkAshmemImageCache::allocAndPinCache(size_t bytes, intptr_t* ID) {
     // In release mode, we do not keep a pointer to this object. It will be destroyed
     // either when pinCache returns NULL or when throwAwayCache is called.
     AshmemRec* pRec = SkNEW_ARGS(AshmemRec, (rec));
-    SkASSERT(ID != NULL);
     *ID = reinterpret_cast<intptr_t>(pRec);
 #ifdef SK_DEBUG
     this->appendRec(pRec);
@@ -89,8 +103,6 @@ void* SkAshmemImageCache::pinCache(intptr_t ID) {
 #endif
         return rec->fAddr;
     }
-    // Purged. Remove the associated AshmemRec:
-    this->removeRec(rec);
     ashmem_unpin_region(fd, 0, 0);
     return NULL;
 }
@@ -107,16 +119,10 @@ void SkAshmemImageCache::releaseCache(intptr_t ID) {
 void SkAshmemImageCache::throwAwayCache(intptr_t ID) {
     SkAutoMutexAcquire ac(&gAshmemMutex);
     AshmemRec* rec = reinterpret_cast<AshmemRec*>(ID);
-#ifdef SK_DEBUG
-    SkASSERT(!rec->fPinned);
-#endif
-    this->removeRec(rec);
-}
-
-void SkAshmemImageCache::removeRec(SkAshmemImageCache::AshmemRec* rec) {
     munmap(rec->fAddr, rec->fSize);
     close(rec->fFD);
 #ifdef SK_DEBUG
+    SkASSERT(!rec->fPinned);
     int index = this->findRec(rec);
     SkASSERT(index >= 0);
     fRecs.remove(index);