| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright 2013 Google Inc. | |
| 3 * | |
| 4 * Use of this source code is governed by a BSD-style license that can be | |
| 5 * found in the LICENSE file. | |
| 6 */ | |
| 7 | |
| 8 #include <unistd.h> | |
| 9 #include <sys/mman.h> | |
| 10 #include "SkDiscardableMemory.h" | |
| 11 #include "SkDiscardableMemoryPool.h" | |
| 12 #include "SkTypes.h" | |
| 13 #include "android/ashmem.h" | |
| 14 | |
| 15 //////////////////////////////////////////////////////////////////////////////// | |
| 16 namespace { | |
| 17 /** | |
| 18 * DiscardableMemory implementation that uses the Android kernel's | |
| 19 * ashmem (Android shared memory). | |
| 20 */ | |
| 21 class SkAshmemDiscardableMemory : public SkDiscardableMemory { | |
| 22 public: | |
| 23 SkAshmemDiscardableMemory(int fd, void* address, size_t size); | |
| 24 virtual ~SkAshmemDiscardableMemory(); | |
| 25 virtual bool lock() SK_OVERRIDE; | |
| 26 virtual void* data() SK_OVERRIDE; | |
| 27 virtual void unlock() SK_OVERRIDE; | |
| 28 static SkAshmemDiscardableMemory* Create(size_t bytes); | |
| 29 | |
| 30 private: | |
| 31 bool fLocked; | |
| 32 int fFd; | |
| 33 void* fMemory; | |
| 34 const size_t fSize; | |
| 35 }; | |
| 36 | |
| 37 SkAshmemDiscardableMemory::SkAshmemDiscardableMemory(int fd, | |
| 38 void* address, | |
| 39 size_t size) | |
| 40 : fLocked(true) // Ashmem pages are pinned by default. | |
| 41 , fFd(fd) | |
| 42 , fMemory(address) | |
| 43 , fSize(size) { | |
| 44 SkASSERT(fFd >= 0); | |
| 45 SkASSERT(fMemory != NULL); | |
| 46 SkASSERT(fSize > 0); | |
| 47 } | |
| 48 | |
| 49 SkAshmemDiscardableMemory::~SkAshmemDiscardableMemory() { | |
| 50 SkASSERT(!fLocked); | |
| 51 if (NULL != fMemory) { | |
| 52 munmap(fMemory, fSize); | |
| 53 } | |
| 54 if (fFd != -1) { | |
| 55 close(fFd); | |
| 56 } | |
| 57 } | |
| 58 | |
| 59 bool SkAshmemDiscardableMemory::lock() { | |
| 60 SkASSERT(!fLocked); | |
| 61 if (-1 == fFd) { | |
| 62 fLocked = false; | |
| 63 return false; | |
| 64 } | |
| 65 SkASSERT(fMemory != NULL); | |
| 66 if (fLocked || (ASHMEM_NOT_PURGED == ashmem_pin_region(fFd, 0, 0))) { | |
| 67 fLocked = true; | |
| 68 return true; | |
| 69 } else { | |
| 70 munmap(fMemory, fSize); | |
| 71 fMemory = NULL; | |
| 72 | |
| 73 close(fFd); | |
| 74 fFd = -1; | |
| 75 fLocked = false; | |
| 76 return false; | |
| 77 } | |
| 78 } | |
| 79 | |
| 80 void* SkAshmemDiscardableMemory::data() { | |
| 81 SkASSERT(fLocked); | |
| 82 return fLocked ? fMemory : NULL; | |
| 83 } | |
| 84 | |
| 85 void SkAshmemDiscardableMemory::unlock() { | |
| 86 SkASSERT(fLocked); | |
| 87 if (fLocked && (fFd != -1)) { | |
| 88 ashmem_unpin_region(fFd, 0, 0); | |
| 89 } | |
| 90 fLocked = false; | |
| 91 } | |
| 92 | |
| 93 SkAshmemDiscardableMemory* SkAshmemDiscardableMemory::Create(size_t bytes) { | |
| 94 // ashmem likes lengths on page boundaries. | |
| 95 const size_t mask = getpagesize() - 1; | |
| 96 size_t size = (bytes + mask) & ~mask; | |
| 97 | |
| 98 static const char name[] = "Skia_Ashmem_Discardable_Memory"; | |
| 99 int fd = ashmem_create_region(name, size); | |
| 100 if (fd < 0) { | |
| 101 return NULL; | |
| 102 } | |
| 103 if (0 != ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE)) { | |
| 104 close(fd); | |
| 105 return NULL; | |
| 106 } | |
| 107 void* addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); | |
| 108 if ((MAP_FAILED == addr) || (NULL == addr)) { | |
| 109 close(fd); | |
| 110 return NULL; | |
| 111 } | |
| 112 | |
| 113 return SkNEW_ARGS(SkAshmemDiscardableMemory, (fd, addr, size)); | |
| 114 } | |
| 115 } // namespace | |
| 116 //////////////////////////////////////////////////////////////////////////////// | |
| 117 | |
| 118 #ifndef SK_ASHMEM_MINIMUM_MEMORY_SIZE | |
| 119 // number taken from android/graphics/BitmapFactory.cpp | |
| 120 #define SK_ASHMEM_MINIMUM_MEMORY_SIZE (32 * 1024) | |
| 121 #endif // SK_ASHMEM_MINIMUM_MEMORY_SIZE | |
| 122 SkDiscardableMemory* SkDiscardableMemory::Create(size_t bytes) { | |
| 123 if (bytes < SK_ASHMEM_MINIMUM_MEMORY_SIZE) { | |
| 124 return SkGetGlobalDiscardableMemoryPool()->create(bytes); | |
| 125 } else { | |
| 126 return SkAshmemDiscardableMemory::Create(bytes); | |
| 127 } | |
| 128 } | |
| OLD | NEW |