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
28 #include <cutils/log.h>
29 #include <cutils/atomic.h>
30
31 #include <hardware/hardware.h>
32 #include <hardware/gralloc.h>
33
34 #include "gralloc_priv.h"
35
36
37 // we need this for now because pmem cannot mmap at an offset
38 #define PMEM_HACK 1
39
40 /* desktop Linux needs a little help with gettid() */
41 #if defined(ARCH_X86) && !defined(HAVE_ANDROID_OS)
42 #define __KERNEL__
43 # include <linux/unistd.h>
gettid()44 pid_t gettid() { return syscall(__NR_gettid);}
45 #undef __KERNEL__
46 #endif
47
48 /*****************************************************************************/
49
gralloc_map(gralloc_module_t const * module,buffer_handle_t handle,void ** vaddr)50 static int gralloc_map(gralloc_module_t const* module,
51 buffer_handle_t handle,
52 void** vaddr)
53 {
54 private_handle_t* hnd = (private_handle_t*)handle;
55 if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
56 size_t size = hnd->size;
57 #if PMEM_HACK
58 size += hnd->offset;
59 #endif
60 void* mappedAddress = mmap(0, size,
61 PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0);
62 if (mappedAddress == MAP_FAILED) {
63 LOGE("Could not mmap handle %p, fd=%d (%s)",
64 handle, hnd->fd, strerror(errno));
65 hnd->base = 0;
66 return -errno;
67 }
68 hnd->base = intptr_t(mappedAddress) + hnd->offset;
69 //LOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p",
70 // hnd->fd, hnd->offset, hnd->size, mappedAddress);
71 }
72 *vaddr = (void*)hnd->base;
73 return 0;
74 }
75
gralloc_unmap(gralloc_module_t const * module,buffer_handle_t handle)76 static int gralloc_unmap(gralloc_module_t const* module,
77 buffer_handle_t handle)
78 {
79 private_handle_t* hnd = (private_handle_t*)handle;
80 if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
81 void* base = (void*)hnd->base;
82 size_t size = hnd->size;
83 #if PMEM_HACK
84 base = (void*)(intptr_t(base) - hnd->offset);
85 size += hnd->offset;
86 #endif
87 //LOGD("unmapping from %p, size=%d", base, size);
88 if (munmap(base, size) < 0) {
89 LOGE("Could not unmap %s", strerror(errno));
90 }
91 }
92 hnd->base = 0;
93 return 0;
94 }
95
96 /*****************************************************************************/
97
98 static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER;
99
100 /*****************************************************************************/
101
gralloc_register_buffer(gralloc_module_t const * module,buffer_handle_t handle)102 int gralloc_register_buffer(gralloc_module_t const* module,
103 buffer_handle_t handle)
104 {
105 if (private_handle_t::validate(handle) < 0)
106 return -EINVAL;
107
108 // In this implementation, we don't need to do anything here
109
110 /* NOTE: we need to initialize the buffer as not mapped/not locked
111 * because it shouldn't when this function is called the first time
112 * in a new process. Ideally these flags shouldn't be part of the
113 * handle, but instead maintained in the kernel or at least
114 * out-of-line
115 */
116
117 // if this handle was created in this process, then we keep it as is.
118 private_handle_t* hnd = (private_handle_t*)handle;
119 if (hnd->pid != getpid()) {
120 hnd->base = 0;
121 hnd->lockState = 0;
122 hnd->writeOwner = 0;
123 }
124 return 0;
125 }
126
gralloc_unregister_buffer(gralloc_module_t const * module,buffer_handle_t handle)127 int gralloc_unregister_buffer(gralloc_module_t const* module,
128 buffer_handle_t handle)
129 {
130 if (private_handle_t::validate(handle) < 0)
131 return -EINVAL;
132
133 /*
134 * If the buffer has been mapped during a lock operation, it's time
135 * to un-map it. It's an error to be here with a locked buffer.
136 * NOTE: the framebuffer is handled differently and is never unmapped.
137 */
138
139 private_handle_t* hnd = (private_handle_t*)handle;
140
141 LOGE_IF(hnd->lockState & private_handle_t::LOCK_STATE_READ_MASK,
142 "[unregister] handle %p still locked (state=%08x)",
143 hnd, hnd->lockState);
144
145 // never unmap buffers that were created in this process
146 if (hnd->pid != getpid()) {
147 if (hnd->lockState & private_handle_t::LOCK_STATE_MAPPED) {
148 gralloc_unmap(module, handle);
149 }
150 hnd->base = 0;
151 hnd->lockState = 0;
152 hnd->writeOwner = 0;
153 }
154 return 0;
155 }
156
terminateBuffer(gralloc_module_t const * module,private_handle_t * hnd)157 int terminateBuffer(gralloc_module_t const* module,
158 private_handle_t* hnd)
159 {
160 /*
161 * If the buffer has been mapped during a lock operation, it's time
162 * to un-map it. It's an error to be here with a locked buffer.
163 */
164
165 LOGE_IF(hnd->lockState & private_handle_t::LOCK_STATE_READ_MASK,
166 "[terminate] handle %p still locked (state=%08x)",
167 hnd, hnd->lockState);
168
169 if (hnd->lockState & private_handle_t::LOCK_STATE_MAPPED) {
170 // this buffer was mapped, unmap it now
171 if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_PMEM) {
172 if (hnd->pid != getpid()) {
173 // ... unless it's a "master" pmem buffer, that is a buffer
174 // mapped in the process it's been allocated.
175 // (see gralloc_alloc_buffer())
176 gralloc_unmap(module, hnd);
177 }
178 } else {
179 gralloc_unmap(module, hnd);
180 }
181 }
182
183 return 0;
184 }
185
gralloc_lock(gralloc_module_t const * module,buffer_handle_t handle,int usage,int l,int t,int w,int h,void ** vaddr)186 int gralloc_lock(gralloc_module_t const* module,
187 buffer_handle_t handle, int usage,
188 int l, int t, int w, int h,
189 void** vaddr)
190 {
191 if (private_handle_t::validate(handle) < 0)
192 return -EINVAL;
193
194 int err = 0;
195 private_handle_t* hnd = (private_handle_t*)handle;
196 int32_t current_value, new_value;
197 int retry;
198
199 do {
200 current_value = hnd->lockState;
201 new_value = current_value;
202
203 if (current_value & private_handle_t::LOCK_STATE_WRITE) {
204 // already locked for write
205 LOGE("handle %p already locked for write", handle);
206 return -EBUSY;
207 } else if (current_value & private_handle_t::LOCK_STATE_READ_MASK) {
208 // already locked for read
209 if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_HW_RENDER)) {
210 LOGE("handle %p already locked for read", handle);
211 return -EBUSY;
212 } else {
213 // this is not an error
214 //LOGD("%p already locked for read... count = %d",
215 // handle, (current_value & ~(1<<31)));
216 }
217 }
218
219 // not currently locked
220 if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_HW_RENDER)) {
221 // locking for write
222 new_value |= private_handle_t::LOCK_STATE_WRITE;
223 }
224 new_value++;
225
226 retry = android_atomic_cmpxchg(current_value, new_value,
227 (volatile int32_t*)&hnd->lockState);
228 } while (retry);
229
230 if (new_value & private_handle_t::LOCK_STATE_WRITE) {
231 // locking for write, store the tid
232 hnd->writeOwner = gettid();
233 }
234
235 if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
236 if (!(current_value & private_handle_t::LOCK_STATE_MAPPED)) {
237 // we need to map for real
238 pthread_mutex_t* const lock = &sMapLock;
239 pthread_mutex_lock(lock);
240 if (!(hnd->lockState & private_handle_t::LOCK_STATE_MAPPED)) {
241 err = gralloc_map(module, handle, vaddr);
242 if (err == 0) {
243 android_atomic_or(private_handle_t::LOCK_STATE_MAPPED,
244 (volatile int32_t*)&(hnd->lockState));
245 }
246 }
247 pthread_mutex_unlock(lock);
248 }
249 *vaddr = (void*)hnd->base;
250 }
251
252 return err;
253 }
254
gralloc_unlock(gralloc_module_t const * module,buffer_handle_t handle)255 int gralloc_unlock(gralloc_module_t const* module,
256 buffer_handle_t handle)
257 {
258 if (private_handle_t::validate(handle) < 0)
259 return -EINVAL;
260
261 private_handle_t* hnd = (private_handle_t*)handle;
262 int32_t current_value, new_value;
263
264 do {
265 current_value = hnd->lockState;
266 new_value = current_value;
267
268 if (current_value & private_handle_t::LOCK_STATE_WRITE) {
269 // locked for write
270 if (hnd->writeOwner == gettid()) {
271 hnd->writeOwner = 0;
272 new_value &= ~private_handle_t::LOCK_STATE_WRITE;
273 }
274 }
275
276 if ((new_value & private_handle_t::LOCK_STATE_READ_MASK) == 0) {
277 LOGE("handle %p not locked", handle);
278 return -EINVAL;
279 }
280
281 new_value--;
282
283 } while (android_atomic_cmpxchg(current_value, new_value,
284 (volatile int32_t*)&hnd->lockState));
285
286 return 0;
287 }
288
289 /*****************************************************************************/
290
gralloc_perform(struct gralloc_module_t const * module,int operation,...)291 int gralloc_perform(struct gralloc_module_t const* module,
292 int operation, ... )
293 {
294 int res = -EINVAL;
295 va_list args;
296 va_start(args, operation);
297
298 switch (operation) {
299 case GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER: {
300 int fd = va_arg(args, int);
301 size_t size = va_arg(args, size_t);
302 size_t offset = va_arg(args, size_t);
303 void* base = va_arg(args, void*);
304 native_handle_t** handle = va_arg(args, native_handle_t**);
305 private_handle_t* hnd = (private_handle_t*)native_handle_create(
306 private_handle_t::sNumFds, private_handle_t::sNumInts);
307 hnd->magic = private_handle_t::sMagic;
308 hnd->fd = fd;
309 hnd->flags = private_handle_t::PRIV_FLAGS_USES_PMEM;
310 hnd->size = size;
311 hnd->offset = offset;
312 hnd->base = intptr_t(base) + offset;
313 hnd->lockState = private_handle_t::LOCK_STATE_MAPPED;
314 *handle = (native_handle_t *)hnd;
315 res = 0;
316 break;
317 }
318 }
319
320 va_end(args);
321 return res;
322 }
323