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 "SkTypes.h" | |
12 #include "android/ashmem.h" | |
13 | |
14 //////////////////////////////////////////////////////////////////////////////// | |
15 namespace { | |
16 /** | |
17 * DiscardableMemory implementation that uses the Android kernel's | |
18 * ashmem (Android shared memory). | |
19 */ | |
20 class SkAshmemDiscardableMemory : public SkDiscardableMemory { | |
21 public: | |
22 SkAshmemDiscardableMemory(int fd, void* address, size_t size); | |
23 virtual ~SkAshmemDiscardableMemory(); | |
24 virtual bool lock() SK_OVERRIDE; | |
25 virtual void* data() SK_OVERRIDE; | |
26 virtual void unlock() SK_OVERRIDE; | |
27 private: | |
28 bool fLocked; | |
scroggo
2013/11/22 14:34:14
nit: names should line up.
hal.canary
2013/11/22 15:17:54
Done.
| |
29 int fFd; | |
30 void* fMemory; | |
31 const size_t fSize; | |
32 }; | |
33 | |
34 SkAshmemDiscardableMemory::SkAshmemDiscardableMemory(int fd, | |
35 void* address, | |
36 size_t size) | |
37 : fLocked(true) | |
38 , fFd(fd) | |
39 , fMemory(address) | |
40 , fSize(size) { | |
41 SkASSERT(fFd >= 0); | |
42 SkASSERT(fMemory != NULL); | |
43 SkASSERT(fSize > 0); | |
44 } | |
45 | |
46 SkAshmemDiscardableMemory::~SkAshmemDiscardableMemory() { | |
47 SkASSERT(!fLocked); | |
48 if (NULL != fMemory) { | |
49 munmap(fMemory, fSize); | |
50 } | |
51 if (fFd != -1) { | |
52 close(fFd); | |
53 } | |
54 } | |
55 | |
56 bool SkAshmemDiscardableMemory::lock() { | |
57 SkASSERT(!fLocked); | |
58 if (-1 == fFd) { | |
59 return fLocked = false; | |
scroggo
2013/11/22 14:34:14
I find this confusing to look at. Is it okay to sa
hal.canary
2013/11/22 15:17:54
Done.
| |
60 } | |
61 SkASSERT(fMemory != NULL); | |
62 if (fLocked || (ASHMEM_NOT_PURGED == ashmem_pin_region(fFd, 0, 0))) { | |
63 return fLocked = true; | |
64 } else { | |
65 munmap(fMemory, fSize); | |
66 fMemory = NULL; | |
67 | |
68 close(fFd); | |
69 fFd = -1; | |
70 return fLocked = false; | |
71 } | |
72 } | |
73 | |
74 void* SkAshmemDiscardableMemory::data() { | |
75 SkASSERT(fLocked); | |
76 return fLocked ? fMemory : NULL; | |
77 } | |
78 | |
79 void SkAshmemDiscardableMemory::unlock() { | |
80 SkASSERT(fLocked); | |
81 if (fLocked && (fFd != -1)) { | |
82 ashmem_unpin_region(fFd, 0, 0); | |
83 } | |
84 fLocked = false; | |
85 } | |
86 } // namespace | |
87 //////////////////////////////////////////////////////////////////////////////// | |
88 | |
89 SkDiscardableMemory* SkDiscardableMemory::Create(size_t bytes) { | |
90 // ashmem likes lengths on page boundaries. | |
91 const size_t mask = getpagesize() - 1; | |
92 size_t size = (bytes + mask) & ~mask; | |
93 | |
94 static const char name[] = "Skia_Ashmem_Discardable_Memory"; | |
95 int fd = ashmem_create_region(name, size); | |
96 if (fd < 0) { | |
97 return NULL; | |
98 } | |
99 if (0 != ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE)) { | |
100 close(fd); | |
101 return NULL; | |
102 } | |
103 void* addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); | |
104 if (MAP_FAILED == addr) { | |
105 close(fd); | |
106 return NULL; | |
107 } | |
108 if (-1 == ashmem_pin_region(fd, 0, 0)) { | |
scroggo
2013/11/22 14:34:14
Is this step necessary? It seems that SkImageRef_a
hal.canary
2013/11/22 15:17:54
SkImageRef_ashmem does not begin in a locked state
scroggo
2013/11/22 15:37:05
SkImageRef_ashmem does not begin in a locked state
scroggo
2013/12/06 16:07:51
Did you see my last comment? I don't think this re
hal.canary
2013/12/06 20:14:42
I had missed your last comment. Thanks for remind
| |
109 // Purge status doesn't matter, only check for errors. | |
110 munmap(addr, size); | |
111 close(fd); | |
112 return NULL; | |
113 } | |
114 | |
115 return SkNEW_ARGS(SkAshmemDiscardableMemory, (fd, addr, size)); | |
116 } | |
117 | |
OLD | NEW |