| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkAshmemImageCache.h" | 8 #include "SkAshmemImageCache.h" |
| 9 #include "SkThread.h" | 9 #include "SkThread.h" |
| 10 | 10 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 #endif | 34 #endif |
| 35 | 35 |
| 36 // ashmem likes lengths on page boundaries. | 36 // ashmem likes lengths on page boundaries. |
| 37 static size_t roundToPageSize(size_t size) { | 37 static size_t roundToPageSize(size_t size) { |
| 38 const size_t mask = getpagesize() - 1; | 38 const size_t mask = getpagesize() - 1; |
| 39 size_t newSize = (size + mask) & ~mask; | 39 size_t newSize = (size + mask) & ~mask; |
| 40 return newSize; | 40 return newSize; |
| 41 } | 41 } |
| 42 | 42 |
| 43 void* SkAshmemImageCache::allocAndPinCache(size_t bytes, intptr_t* ID) { | 43 void* SkAshmemImageCache::allocAndPinCache(size_t bytes, intptr_t* ID) { |
| 44 SkASSERT(ID != NULL); |
| 45 |
| 46 SkAutoMutexAcquire ac(&gAshmemMutex); |
| 47 |
| 48 if (*ID != SkImageCache::UNINITIALIZED_ID) { |
| 49 // This rec was previously allocated, but pinCache subsequently |
| 50 // failed. |
| 51 AshmemRec* pRec = reinterpret_cast<AshmemRec*>(*ID); |
| 52 SkASSERT(roundToPageSize(bytes) == pRec->fSize); |
| 53 SkASSERT(pRec->fFD != -1); |
| 54 (void) ashmem_pin_region(pRec->fFD, 0, 0); |
| 55 #ifdef SK_DEBUG |
| 56 pRec->fPinned = true; |
| 57 #endif |
| 58 return pRec->fAddr; |
| 59 } |
| 60 |
| 44 AshmemRec rec; | 61 AshmemRec rec; |
| 45 rec.fSize = roundToPageSize(bytes); | 62 rec.fSize = roundToPageSize(bytes); |
| 46 | 63 |
| 47 SkAutoMutexAcquire ac(&gAshmemMutex); | |
| 48 | |
| 49 rec.fFD = ashmem_create_region(NULL, rec.fSize); | 64 rec.fFD = ashmem_create_region(NULL, rec.fSize); |
| 50 if (-1 == rec.fFD) { | 65 if (-1 == rec.fFD) { |
| 51 SkDebugf("ashmem_create_region failed\n"); | 66 SkDebugf("ashmem_create_region failed\n"); |
| 52 return NULL; | 67 return NULL; |
| 53 } | 68 } |
| 54 int err = ashmem_set_prot_region(rec.fFD, PROT_READ | PROT_WRITE); | 69 int err = ashmem_set_prot_region(rec.fFD, PROT_READ | PROT_WRITE); |
| 55 if (err != 0) { | 70 if (err != 0) { |
| 56 SkDebugf("ashmem_set_prot_region failed\n"); | 71 SkDebugf("ashmem_set_prot_region failed\n"); |
| 57 close(rec.fFD); | 72 close(rec.fFD); |
| 58 return NULL; | 73 return NULL; |
| 59 } | 74 } |
| 60 rec.fAddr = mmap(NULL, rec.fSize, PROT_READ | PROT_WRITE, MAP_PRIVATE, rec.f
FD, 0); | 75 rec.fAddr = mmap(NULL, rec.fSize, PROT_READ | PROT_WRITE, MAP_PRIVATE, rec.f
FD, 0); |
| 61 if (-1 == (long) rec.fAddr) { | 76 if (-1 == (long) rec.fAddr) { |
| 62 SkDebugf("mmap failed\n"); | 77 SkDebugf("mmap failed\n"); |
| 63 close(rec.fFD); | 78 close(rec.fFD); |
| 64 return NULL; | 79 return NULL; |
| 65 } | 80 } |
| 66 (void) ashmem_pin_region(rec.fFD, 0, 0); | 81 (void) ashmem_pin_region(rec.fFD, 0, 0); |
| 67 #ifdef SK_DEBUG | 82 #ifdef SK_DEBUG |
| 68 rec.fPinned = true; | 83 rec.fPinned = true; |
| 69 #endif | 84 #endif |
| 70 // In release mode, we do not keep a pointer to this object. It will be dest
royed | 85 // In release mode, we do not keep a pointer to this object. It will be dest
royed |
| 71 // either when pinCache returns NULL or when throwAwayCache is called. | 86 // either when pinCache returns NULL or when throwAwayCache is called. |
| 72 AshmemRec* pRec = SkNEW_ARGS(AshmemRec, (rec)); | 87 AshmemRec* pRec = SkNEW_ARGS(AshmemRec, (rec)); |
| 73 SkASSERT(ID != NULL); | |
| 74 *ID = reinterpret_cast<intptr_t>(pRec); | 88 *ID = reinterpret_cast<intptr_t>(pRec); |
| 75 #ifdef SK_DEBUG | 89 #ifdef SK_DEBUG |
| 76 this->appendRec(pRec); | 90 this->appendRec(pRec); |
| 77 #endif | 91 #endif |
| 78 return rec.fAddr; | 92 return rec.fAddr; |
| 79 } | 93 } |
| 80 | 94 |
| 81 void* SkAshmemImageCache::pinCache(intptr_t ID) { | 95 void* SkAshmemImageCache::pinCache(intptr_t ID) { |
| 82 SkAutoMutexAcquire ac(&gAshmemMutex); | 96 SkAutoMutexAcquire ac(&gAshmemMutex); |
| 83 AshmemRec* rec = reinterpret_cast<AshmemRec*>(ID); | 97 AshmemRec* rec = reinterpret_cast<AshmemRec*>(ID); |
| 84 const int fd = rec->fFD; | 98 const int fd = rec->fFD; |
| 85 int pin = ashmem_pin_region(fd, 0, 0); | 99 int pin = ashmem_pin_region(fd, 0, 0); |
| 86 if (ASHMEM_NOT_PURGED == pin) { | 100 if (ASHMEM_NOT_PURGED == pin) { |
| 87 #ifdef SK_DEBUG | 101 #ifdef SK_DEBUG |
| 88 rec->fPinned = true; | 102 rec->fPinned = true; |
| 89 #endif | 103 #endif |
| 90 return rec->fAddr; | 104 return rec->fAddr; |
| 91 } | 105 } |
| 92 // Purged. Remove the associated AshmemRec: | |
| 93 this->removeRec(rec); | |
| 94 ashmem_unpin_region(fd, 0, 0); | 106 ashmem_unpin_region(fd, 0, 0); |
| 95 return NULL; | 107 return NULL; |
| 96 } | 108 } |
| 97 | 109 |
| 98 void SkAshmemImageCache::releaseCache(intptr_t ID) { | 110 void SkAshmemImageCache::releaseCache(intptr_t ID) { |
| 99 SkAutoMutexAcquire ac(&gAshmemMutex); | 111 SkAutoMutexAcquire ac(&gAshmemMutex); |
| 100 AshmemRec* rec = reinterpret_cast<AshmemRec*>(ID); | 112 AshmemRec* rec = reinterpret_cast<AshmemRec*>(ID); |
| 101 ashmem_unpin_region(rec->fFD, 0, 0); | 113 ashmem_unpin_region(rec->fFD, 0, 0); |
| 102 #ifdef SK_DEBUG | 114 #ifdef SK_DEBUG |
| 103 rec->fPinned = false; | 115 rec->fPinned = false; |
| 104 #endif | 116 #endif |
| 105 } | 117 } |
| 106 | 118 |
| 107 void SkAshmemImageCache::throwAwayCache(intptr_t ID) { | 119 void SkAshmemImageCache::throwAwayCache(intptr_t ID) { |
| 108 SkAutoMutexAcquire ac(&gAshmemMutex); | 120 SkAutoMutexAcquire ac(&gAshmemMutex); |
| 109 AshmemRec* rec = reinterpret_cast<AshmemRec*>(ID); | 121 AshmemRec* rec = reinterpret_cast<AshmemRec*>(ID); |
| 110 #ifdef SK_DEBUG | |
| 111 SkASSERT(!rec->fPinned); | |
| 112 #endif | |
| 113 this->removeRec(rec); | |
| 114 } | |
| 115 | |
| 116 void SkAshmemImageCache::removeRec(SkAshmemImageCache::AshmemRec* rec) { | |
| 117 munmap(rec->fAddr, rec->fSize); | 122 munmap(rec->fAddr, rec->fSize); |
| 118 close(rec->fFD); | 123 close(rec->fFD); |
| 119 #ifdef SK_DEBUG | 124 #ifdef SK_DEBUG |
| 125 SkASSERT(!rec->fPinned); |
| 120 int index = this->findRec(rec); | 126 int index = this->findRec(rec); |
| 121 SkASSERT(index >= 0); | 127 SkASSERT(index >= 0); |
| 122 fRecs.remove(index); | 128 fRecs.remove(index); |
| 123 #endif | 129 #endif |
| 124 SkDELETE(rec); | 130 SkDELETE(rec); |
| 125 } | 131 } |
| 126 | 132 |
| 127 #ifdef SK_DEBUG | 133 #ifdef SK_DEBUG |
| 128 void SkAshmemImageCache::appendRec(SkAshmemImageCache::AshmemRec* rec) { | 134 void SkAshmemImageCache::appendRec(SkAshmemImageCache::AshmemRec* rec) { |
| 129 int index = this->findRec(rec); | 135 int index = this->findRec(rec); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 146 SkAutoMutexAcquire ac(&gAshmemMutex); | 152 SkAutoMutexAcquire ac(&gAshmemMutex); |
| 147 AshmemRec* rec = reinterpret_cast<AshmemRec*>(ID); | 153 AshmemRec* rec = reinterpret_cast<AshmemRec*>(ID); |
| 148 int index = this->findRec(rec); | 154 int index = this->findRec(rec); |
| 149 if (index < 0) { | 155 if (index < 0) { |
| 150 return SkImageCache::kThrownAway_CacheStatus; | 156 return SkImageCache::kThrownAway_CacheStatus; |
| 151 } | 157 } |
| 152 return rec->fPinned ? SkImageCache::kPinned_CacheStatus | 158 return rec->fPinned ? SkImageCache::kPinned_CacheStatus |
| 153 : SkImageCache::kUnpinned_CacheStatus; | 159 : SkImageCache::kUnpinned_CacheStatus; |
| 154 } | 160 } |
| 155 #endif | 161 #endif |
| OLD | NEW |