1 /*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <limits.h>
18 #include <errno.h>
19 #include <pthread.h>
20 #include <unistd.h>
21 #include <string.h>
22 #include <stdarg.h>
23
24 #include <sys/mman.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <sys/ioctl.h>
28
29 #include <cutils/log.h>
30 #include <cutils/atomic.h>
31
32 #include <hardware/hardware.h>
33 #include <hardware/gralloc.h>
34
35 #include <linux/android_pmem.h>
36
37 #include "gralloc_priv.h"
38
39
40 // we need this for now because pmem cannot mmap at an offset
41 #define PMEM_HACK 1
42
43 /* desktop Linux needs a little help with gettid() */
44 #if defined(ARCH_X86) && !defined(HAVE_ANDROID_OS)
45 #define __KERNEL__
46 # include <linux/unistd.h>
gettid()47 pid_t gettid() { return syscall(__NR_gettid);}
48 #undef __KERNEL__
49 #endif
50
51 /*****************************************************************************/
52
gralloc_map(gralloc_module_t const * module,buffer_handle_t handle,void ** vaddr)53 static int gralloc_map(gralloc_module_t const* module,
54 buffer_handle_t handle,
55 void** vaddr)
56 {
57 private_handle_t* hnd = (private_handle_t*)handle;
58 if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
59 size_t size = hnd->size;
60 #if PMEM_HACK
61 size += hnd->offset;
62 #endif
63 void* mappedAddress = mmap(0, size,
64 PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0);
65 if (mappedAddress == MAP_FAILED) {
66 ALOGE("Could not mmap handle %p, fd=%d (%s)",
67 handle, hnd->fd, strerror(errno));
68 hnd->base = 0;
69 return -errno;
70 }
71 hnd->base = intptr_t(mappedAddress) + hnd->offset;
72 //ALOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p",
73 // hnd->fd, hnd->offset, hnd->size, mappedAddress);
74 }
75 *vaddr = (void*)hnd->base;
76 return 0;
77 }
78
gralloc_unmap(gralloc_module_t const * module,buffer_handle_t handle)79 static int gralloc_unmap(gralloc_module_t const* module,
80 buffer_handle_t handle)
81 {
82 private_handle_t* hnd = (private_handle_t*)handle;
83 if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
84 void* base = (void*)hnd->base;
85 size_t size = hnd->size;
86 #if PMEM_HACK
87 base = (void*)(intptr_t(base) - hnd->offset);
88 size += hnd->offset;
89 #endif
90 //ALOGD("unmapping from %p, size=%d", base, size);
91 if (munmap(base, size) < 0) {
92 ALOGE("Could not unmap %s", strerror(errno));
93 }
94 }
95 hnd->base = 0;
96 return 0;
97 }
98
99 /*****************************************************************************/
100
101 static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER;
102
103 /*****************************************************************************/
104
gralloc_register_buffer(gralloc_module_t const * module,buffer_handle_t handle)105 int gralloc_register_buffer(gralloc_module_t const* module,
106 buffer_handle_t handle)
107 {
108 if (private_handle_t::validate(handle) < 0)
109 return -EINVAL;
110
111 // In this implementation, we don't need to do anything here
112
113 /* NOTE: we need to initialize the buffer as not mapped/not locked
114 * because it shouldn't when this function is called the first time
115 * in a new process. Ideally these flags shouldn't be part of the
116 * handle, but instead maintained in the kernel or at least
117 * out-of-line
118 */
119
120 // if this handle was created in this process, then we keep it as is.
121 private_handle_t* hnd = (private_handle_t*)handle;
122 if (hnd->pid != getpid()) {
123 hnd->base = 0;
124 hnd->lockState = 0;
125 hnd->writeOwner = 0;
126 }
127 return 0;
128 }
129
gralloc_unregister_buffer(gralloc_module_t const * module,buffer_handle_t handle)130 int gralloc_unregister_buffer(gralloc_module_t const* module,
131 buffer_handle_t handle)
132 {
133 if (private_handle_t::validate(handle) < 0)
134 return -EINVAL;
135
136 /*
137 * If the buffer has been mapped during a lock operation, it's time
138 * to un-map it. It's an error to be here with a locked buffer.
139 * NOTE: the framebuffer is handled differently and is never unmapped.
140 */
141
142 private_handle_t* hnd = (private_handle_t*)handle;
143
144 ALOGE_IF(hnd->lockState & private_handle_t::LOCK_STATE_READ_MASK,
145 "[unregister] handle %p still locked (state=%08x)",
146 hnd, hnd->lockState);
147
148 // never unmap buffers that were created in this process
149 if (hnd->pid != getpid()) {
150 if (hnd->lockState & private_handle_t::LOCK_STATE_MAPPED) {
151 gralloc_unmap(module, handle);
152 }
153 hnd->base = 0;
154 hnd->lockState = 0;
155 hnd->writeOwner = 0;
156 }
157 return 0;
158 }
159
terminateBuffer(gralloc_module_t const * module,private_handle_t * hnd)160 int terminateBuffer(gralloc_module_t const* module,
161 private_handle_t* hnd)
162 {
163 /*
164 * If the buffer has been mapped during a lock operation, it's time
165 * to un-map it. It's an error to be here with a locked buffer.
166 */
167
168 ALOGE_IF(hnd->lockState & private_handle_t::LOCK_STATE_READ_MASK,
169 "[terminate] handle %p still locked (state=%08x)",
170 hnd, hnd->lockState);
171
172 if (hnd->lockState & private_handle_t::LOCK_STATE_MAPPED) {
173 // this buffer was mapped, unmap it now
174 if ((hnd->flags & private_handle_t::PRIV_FLAGS_USES_PMEM) ||
175 (hnd->flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP)) {
176 if (hnd->pid != getpid()) {
177 // ... unless it's a "master" pmem buffer, that is a buffer
178 // mapped in the process it's been allocated.
179 // (see gralloc_alloc_buffer())
180 gralloc_unmap(module, hnd);
181 }
182 } else {
183 gralloc_unmap(module, hnd);
184 }
185 }
186
187 return 0;
188 }
189
gralloc_lock(gralloc_module_t const * module,buffer_handle_t handle,int usage,int l,int t,int w,int h,void ** vaddr)190 int gralloc_lock(gralloc_module_t const* module,
191 buffer_handle_t handle, int usage,
192 int l, int t, int w, int h,
193 void** vaddr)
194 {
195 if (private_handle_t::validate(handle) < 0)
196 return -EINVAL;
197
198 int err = 0;
199 private_handle_t* hnd = (private_handle_t*)handle;
200 int32_t current_value, new_value;
201 int retry;
202
203 do {
204 current_value = hnd->lockState;
205 new_value = current_value;
206
207 if (current_value & private_handle_t::LOCK_STATE_WRITE) {
208 // already locked for write
209 ALOGE("handle %p already locked for write", handle);
210 return -EBUSY;
211 } else if (current_value & private_handle_t::LOCK_STATE_READ_MASK) {
212 // already locked for read
213 if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_HW_RENDER)) {
214 ALOGE("handle %p already locked for read", handle);
215 return -EBUSY;
216 } else {
217 // this is not an error
218 //ALOGD("%p already locked for read... count = %d",
219 // handle, (current_value & ~(1<<31)));
220 }
221 }
222
223 // not currently locked
224 if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_HW_RENDER)) {
225 // locking for write
226 new_value |= private_handle_t::LOCK_STATE_WRITE;
227 }
228 new_value++;
229
230 retry = android_atomic_cmpxchg(current_value, new_value,
231 (volatile int32_t*)&hnd->lockState);
232 } while (retry);
233
234 if (new_value & private_handle_t::LOCK_STATE_WRITE) {
235 // locking for write, store the tid
236 hnd->writeOwner = gettid();
237 }
238
239 // if requesting sw write for non-framebuffer handles, flag for
240 // flushing at unlock
241
242 const uint32_t pmemMask =
243 private_handle_t::PRIV_FLAGS_USES_PMEM |
244 private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP;
245
246 if ((usage & GRALLOC_USAGE_SW_WRITE_MASK) &&
247 (hnd->flags & pmemMask) &&
248 !(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
249 hnd->flags |= private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
250 }
251
252 if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
253 if (!(current_value & private_handle_t::LOCK_STATE_MAPPED)) {
254 // we need to map for real
255 pthread_mutex_t* const lock = &sMapLock;
256 pthread_mutex_lock(lock);
257 if (!(hnd->lockState & private_handle_t::LOCK_STATE_MAPPED)) {
258 err = gralloc_map(module, handle, vaddr);
259 if (err == 0) {
260 android_atomic_or(private_handle_t::LOCK_STATE_MAPPED,
261 (volatile int32_t*)&(hnd->lockState));
262 }
263 }
264 pthread_mutex_unlock(lock);
265 }
266 *vaddr = (void*)hnd->base;
267 }
268
269 return err;
270 }
271
gralloc_unlock(gralloc_module_t const * module,buffer_handle_t handle)272 int gralloc_unlock(gralloc_module_t const* module,
273 buffer_handle_t handle)
274 {
275 if (private_handle_t::validate(handle) < 0)
276 return -EINVAL;
277
278 private_handle_t* hnd = (private_handle_t*)handle;
279 int32_t current_value, new_value;
280
281 if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) {
282 struct pmem_region region;
283 int err;
284
285 region.offset = hnd->offset;
286 region.len = hnd->size;
287 err = ioctl(hnd->fd, PMEM_CACHE_FLUSH, ®ion);
288 ALOGE_IF(err < 0, "cannot flush handle %p (offs=%x len=%x)\n",
289 hnd, hnd->offset, hnd->size);
290 hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
291 }
292
293 do {
294 current_value = hnd->lockState;
295 new_value = current_value;
296
297 if (current_value & private_handle_t::LOCK_STATE_WRITE) {
298 // locked for write
299 if (hnd->writeOwner == gettid()) {
300 hnd->writeOwner = 0;
301 new_value &= ~private_handle_t::LOCK_STATE_WRITE;
302 }
303 }
304
305 if ((new_value & private_handle_t::LOCK_STATE_READ_MASK) == 0) {
306 ALOGE("handle %p not locked", handle);
307 return -EINVAL;
308 }
309
310 new_value--;
311
312 } while (android_atomic_cmpxchg(current_value, new_value,
313 (volatile int32_t*)&hnd->lockState));
314
315 return 0;
316 }
317
318 /*****************************************************************************/
319
gralloc_perform(struct gralloc_module_t const * module,int operation,...)320 int gralloc_perform(struct gralloc_module_t const* module,
321 int operation, ... )
322 {
323 int res = -EINVAL;
324 return res;
325 }
326