blob: e2caf79e73b9c7e2d9cf3a7980df16156e703813 [file] [log] [blame]
Mathias Agopiana8a75162009-04-10 14:24:31 -07001/*
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>
Mathias Agopian8c4ab1f2009-06-11 16:32:05 -070020#include <unistd.h>
Marco Nelissena4b587c2009-07-07 09:29:00 -070021#include <string.h>
Mathias Agopiana8a75162009-04-10 14:24:31 -070022
23#include <sys/mman.h>
24#include <sys/stat.h>
25#include <sys/types.h>
26
27#include <cutils/log.h>
28#include <cutils/atomic.h>
29
30#include <hardware/hardware.h>
31#include <hardware/gralloc.h>
32
33#include "gralloc_priv.h"
34
Mathias Agopian8c4ab1f2009-06-11 16:32:05 -070035
36// we need this for now because pmem cannot mmap at an offset
37#define PMEM_HACK 1
38
Marco Nelissena4b587c2009-07-07 09:29:00 -070039/* desktop Linux needs a little help with gettid() */
40#if defined(ARCH_X86) && !defined(HAVE_ANDROID_OS)
41#define __KERNEL__
42# include <linux/unistd.h>
43pid_t gettid() { return syscall(__NR_gettid);}
44#undef __KERNEL__
45#endif
46
Mathias Agopiana8a75162009-04-10 14:24:31 -070047/*****************************************************************************/
48
Mathias Agopian51156652009-06-09 18:55:49 -070049static int gralloc_map(gralloc_module_t const* module,
Mathias Agopiana8a75162009-04-10 14:24:31 -070050 buffer_handle_t handle,
51 void** vaddr)
52{
Mathias Agopian51156652009-06-09 18:55:49 -070053 private_handle_t* hnd = (private_handle_t*)handle;
54 if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
Mathias Agopian8c4ab1f2009-06-11 16:32:05 -070055 size_t size = hnd->size;
56#if PMEM_HACK
57 size += hnd->offset;
58#endif
59 void* mappedAddress = mmap(0, size,
60 PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0);
Mathias Agopian51156652009-06-09 18:55:49 -070061 if (mappedAddress == MAP_FAILED) {
Mathias Agopian8c4ab1f2009-06-11 16:32:05 -070062 LOGE("Could not mmap %s", strerror(errno));
Mathias Agopian51156652009-06-09 18:55:49 -070063 return -errno;
64 }
Mathias Agopian8c4ab1f2009-06-11 16:32:05 -070065 hnd->base = intptr_t(mappedAddress) + hnd->offset;
66 //LOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p",
67 // hnd->fd, hnd->offset, hnd->size, mappedAddress);
Mathias Agopiana8a75162009-04-10 14:24:31 -070068 }
Mathias Agopian51156652009-06-09 18:55:49 -070069 *vaddr = (void*)hnd->base;
70 return 0;
Mathias Agopiana8a75162009-04-10 14:24:31 -070071}
72
Mathias Agopian51156652009-06-09 18:55:49 -070073static int gralloc_unmap(gralloc_module_t const* module,
Mathias Agopiana8a75162009-04-10 14:24:31 -070074 buffer_handle_t handle)
75{
Mathias Agopian51156652009-06-09 18:55:49 -070076 private_handle_t* hnd = (private_handle_t*)handle;
77 if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
Mathias Agopianbd80b382009-07-07 17:53:43 -070078 void* base = (void*)hnd->base;
79 size_t size = hnd->size;
80#if PMEM_HACK
81 base = (void*)(intptr_t(base) - hnd->offset);
82 size += hnd->offset;
83#endif
84 //LOGD("unmapping from %p, size=%d", base, size);
85 if (munmap(base, size) < 0) {
Mathias Agopian8c4ab1f2009-06-11 16:32:05 -070086 LOGE("Could not unmap %s", strerror(errno));
Mathias Agopian51156652009-06-09 18:55:49 -070087 }
Mathias Agopiana8a75162009-04-10 14:24:31 -070088 }
Mathias Agopian51156652009-06-09 18:55:49 -070089 hnd->base = 0;
90 return 0;
Mathias Agopiana8a75162009-04-10 14:24:31 -070091}
92
Mathias Agopian51156652009-06-09 18:55:49 -070093/*****************************************************************************/
94
95static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER;
96
97/*****************************************************************************/
98
Mathias Agopian988b8bd2009-05-04 14:26:56 -070099int gralloc_register_buffer(gralloc_module_t const* module,
100 buffer_handle_t handle)
101{
102 if (private_handle_t::validate(handle) < 0)
103 return -EINVAL;
Mathias Agopian51156652009-06-09 18:55:49 -0700104
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700105 // In this implementation, we don't need to do anything here
106
Mathias Agopian51156652009-06-09 18:55:49 -0700107 /* NOTE: we need to initialize the buffer as not mapped/not locked
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700108 * because it shouldn't when this function is called the first time
Mathias Agopian51156652009-06-09 18:55:49 -0700109 * in a new process. Ideally these flags shouldn't be part of the
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700110 * handle, but instead maintained in the kernel or at least
111 * out-of-line
112 */
Mathias Agopian8c4ab1f2009-06-11 16:32:05 -0700113
114 // if this handle was created in this process, then we keep it as is.
Mathias Agopian51156652009-06-09 18:55:49 -0700115 private_handle_t* hnd = (private_handle_t*)handle;
Mathias Agopian8c4ab1f2009-06-11 16:32:05 -0700116 if (hnd->pid != getpid()) {
117 hnd->base = 0;
118 hnd->lockState = 0;
119 hnd->writeOwner = 0;
120 }
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700121 return 0;
122}
123
124int gralloc_unregister_buffer(gralloc_module_t const* module,
125 buffer_handle_t handle)
126{
127 if (private_handle_t::validate(handle) < 0)
128 return -EINVAL;
129
130 /*
131 * If the buffer has been mapped during a lock operation, it's time
Mathias Agopian51156652009-06-09 18:55:49 -0700132 * to un-map it. It's an error to be here with a locked buffer.
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700133 * NOTE: the framebuffer is handled differently and is never unmapped.
134 */
135
Mathias Agopian51156652009-06-09 18:55:49 -0700136 private_handle_t* hnd = (private_handle_t*)handle;
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700137
Mathias Agopian51156652009-06-09 18:55:49 -0700138 LOGE_IF(hnd->lockState & private_handle_t::LOCK_STATE_READ_MASK,
Mathias Agopian05eacf52009-07-13 18:32:37 -0700139 "[unregister] handle %p still locked (state=%08x)",
Mathias Agopian485e6982009-05-05 20:21:57 -0700140 hnd, hnd->lockState);
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700141
Mathias Agopian8c4ab1f2009-06-11 16:32:05 -0700142 // never unmap buffers that were created in this process
143 if (hnd->pid != getpid()) {
144 if (hnd->lockState & private_handle_t::LOCK_STATE_MAPPED) {
145 gralloc_unmap(module, handle);
146 }
147 hnd->base = 0;
148 hnd->lockState = 0;
149 hnd->writeOwner = 0;
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700150 }
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700151 return 0;
152}
Mathias Agopiana8a75162009-04-10 14:24:31 -0700153
Mathias Agopianbd80b382009-07-07 17:53:43 -0700154int terminateBuffer(gralloc_module_t const* module,
155 private_handle_t* hnd)
156{
157 /*
158 * If the buffer has been mapped during a lock operation, it's time
159 * to un-map it. It's an error to be here with a locked buffer.
160 */
161
162 LOGE_IF(hnd->lockState & private_handle_t::LOCK_STATE_READ_MASK,
Mathias Agopian05eacf52009-07-13 18:32:37 -0700163 "[terminate] handle %p still locked (state=%08x)",
Mathias Agopianbd80b382009-07-07 17:53:43 -0700164 hnd, hnd->lockState);
165
166 if (hnd->lockState & private_handle_t::LOCK_STATE_MAPPED) {
167 // this buffer was mapped, unmap it now
168 if ((hnd->flags & private_handle_t::PRIV_FLAGS_USES_PMEM) &&
169 (hnd->pid == getpid())) {
170 // ... unless it's a "master" pmem buffer, that is a buffer
171 // mapped in the process it's been allocated.
172 // (see gralloc_alloc_buffer())
173 } else {
174 gralloc_unmap(module, hnd);
175 }
176 }
177
178 return 0;
179}
180
Mathias Agopiana8a75162009-04-10 14:24:31 -0700181int gralloc_lock(gralloc_module_t const* module,
182 buffer_handle_t handle, int usage,
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700183 int l, int t, int w, int h,
184 void** vaddr)
Mathias Agopiana8a75162009-04-10 14:24:31 -0700185{
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700186 if (private_handle_t::validate(handle) < 0)
187 return -EINVAL;
188
189 int err = 0;
Mathias Agopian51156652009-06-09 18:55:49 -0700190 private_handle_t* hnd = (private_handle_t*)handle;
Mathias Agopian485e6982009-05-05 20:21:57 -0700191 int32_t current_value, new_value;
192 int retry;
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700193
Mathias Agopian485e6982009-05-05 20:21:57 -0700194 do {
195 current_value = hnd->lockState;
196 new_value = current_value;
Mathias Agopian51156652009-06-09 18:55:49 -0700197
198 if (current_value & private_handle_t::LOCK_STATE_WRITE) {
Mathias Agopian485e6982009-05-05 20:21:57 -0700199 // already locked for write
200 LOGE("handle %p already locked for write", handle);
201 return -EBUSY;
Mathias Agopian51156652009-06-09 18:55:49 -0700202 } else if (current_value & private_handle_t::LOCK_STATE_READ_MASK) {
Mathias Agopian485e6982009-05-05 20:21:57 -0700203 // already locked for read
204 if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_HW_RENDER)) {
205 LOGE("handle %p already locked for read", handle);
206 return -EBUSY;
207 } else {
Mathias Agopian82f7c042009-06-03 19:03:26 -0700208 // this is not an error
209 //LOGD("%p already locked for read... count = %d",
210 // handle, (current_value & ~(1<<31)));
Mathias Agopian485e6982009-05-05 20:21:57 -0700211 }
212 }
213
214 // not currently locked
215 if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_HW_RENDER)) {
216 // locking for write
Mathias Agopian51156652009-06-09 18:55:49 -0700217 new_value |= private_handle_t::LOCK_STATE_WRITE;
Mathias Agopian485e6982009-05-05 20:21:57 -0700218 }
219 new_value++;
220
221 retry = android_atomic_cmpxchg(current_value, new_value,
222 (volatile int32_t*)&hnd->lockState);
223 } while (retry);
Mathias Agopian51156652009-06-09 18:55:49 -0700224
225 if (new_value & private_handle_t::LOCK_STATE_WRITE) {
Mathias Agopian485e6982009-05-05 20:21:57 -0700226 // locking for write, store the tid
227 hnd->writeOwner = gettid();
228 }
229
230 if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
Mathias Agopian51156652009-06-09 18:55:49 -0700231 if (!(current_value & private_handle_t::LOCK_STATE_MAPPED)) {
232 // we need to map for real
233 pthread_mutex_t* const lock = &sMapLock;
234 pthread_mutex_lock(lock);
235 if (!(hnd->lockState & private_handle_t::LOCK_STATE_MAPPED)) {
236 err = gralloc_map(module, handle, vaddr);
237 if (err == 0) {
238 android_atomic_or(private_handle_t::LOCK_STATE_MAPPED,
239 (volatile int32_t*)&(hnd->lockState));
240 }
241 }
242 pthread_mutex_unlock(lock);
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700243 }
Mathias Agopian51156652009-06-09 18:55:49 -0700244 *vaddr = (void*)hnd->base;
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700245 }
Mathias Agopian485e6982009-05-05 20:21:57 -0700246
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700247 return err;
Mathias Agopiana8a75162009-04-10 14:24:31 -0700248}
249
250int gralloc_unlock(gralloc_module_t const* module,
251 buffer_handle_t handle)
252{
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700253 if (private_handle_t::validate(handle) < 0)
254 return -EINVAL;
255
Mathias Agopian51156652009-06-09 18:55:49 -0700256 private_handle_t* hnd = (private_handle_t*)handle;
Mathias Agopian485e6982009-05-05 20:21:57 -0700257 int32_t current_value, new_value;
Mathias Agopian988b8bd2009-05-04 14:26:56 -0700258
Mathias Agopian485e6982009-05-05 20:21:57 -0700259 do {
260 current_value = hnd->lockState;
261 new_value = current_value;
262
Mathias Agopian51156652009-06-09 18:55:49 -0700263 if (current_value & private_handle_t::LOCK_STATE_WRITE) {
Mathias Agopian485e6982009-05-05 20:21:57 -0700264 // locked for write
265 if (hnd->writeOwner == gettid()) {
266 hnd->writeOwner = 0;
Mathias Agopian51156652009-06-09 18:55:49 -0700267 new_value &= ~private_handle_t::LOCK_STATE_WRITE;
Mathias Agopian485e6982009-05-05 20:21:57 -0700268 }
269 }
270
Mathias Agopian51156652009-06-09 18:55:49 -0700271 if ((new_value & private_handle_t::LOCK_STATE_READ_MASK) == 0) {
Mathias Agopian485e6982009-05-05 20:21:57 -0700272 LOGE("handle %p not locked", handle);
273 return -EINVAL;
274 }
275
276 new_value--;
277
278 } while (android_atomic_cmpxchg(current_value, new_value,
279 (volatile int32_t*)&hnd->lockState));
280
Mathias Agopiana8a75162009-04-10 14:24:31 -0700281 return 0;
282}