mapper.cpp revision a4b587cb063dfd1b11f0006b0149e5e3045cc873
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 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 35 36// we need this for now because pmem cannot mmap at an offset 37#define PMEM_HACK 1 38 39/* 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 47/*****************************************************************************/ 48 49static int gralloc_map(gralloc_module_t const* module, 50 buffer_handle_t handle, 51 void** vaddr) 52{ 53 private_handle_t* hnd = (private_handle_t*)handle; 54 if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { 55 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); 61 if (mappedAddress == MAP_FAILED) { 62 LOGE("Could not mmap %s", strerror(errno)); 63 return -errno; 64 } 65 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); 68 } 69 *vaddr = (void*)hnd->base; 70 return 0; 71} 72 73static int gralloc_unmap(gralloc_module_t const* module, 74 buffer_handle_t handle) 75{ 76 private_handle_t* hnd = (private_handle_t*)handle; 77 if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { 78 if (munmap((void*)hnd->base, hnd->size) < 0) { 79 LOGE("Could not unmap %s", strerror(errno)); 80 } 81 } 82 hnd->base = 0; 83 return 0; 84} 85 86/*****************************************************************************/ 87 88static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER; 89 90/*****************************************************************************/ 91 92int gralloc_register_buffer(gralloc_module_t const* module, 93 buffer_handle_t handle) 94{ 95 if (private_handle_t::validate(handle) < 0) 96 return -EINVAL; 97 98 // In this implementation, we don't need to do anything here 99 100 /* NOTE: we need to initialize the buffer as not mapped/not locked 101 * because it shouldn't when this function is called the first time 102 * in a new process. Ideally these flags shouldn't be part of the 103 * handle, but instead maintained in the kernel or at least 104 * out-of-line 105 */ 106 107 // if this handle was created in this process, then we keep it as is. 108 private_handle_t* hnd = (private_handle_t*)handle; 109 if (hnd->pid != getpid()) { 110 hnd->base = 0; 111 hnd->lockState = 0; 112 hnd->writeOwner = 0; 113 } 114 return 0; 115} 116 117int gralloc_unregister_buffer(gralloc_module_t const* module, 118 buffer_handle_t handle) 119{ 120 if (private_handle_t::validate(handle) < 0) 121 return -EINVAL; 122 123 /* 124 * If the buffer has been mapped during a lock operation, it's time 125 * to un-map it. It's an error to be here with a locked buffer. 126 * NOTE: the framebuffer is handled differently and is never unmapped. 127 */ 128 129 private_handle_t* hnd = (private_handle_t*)handle; 130 131 LOGE_IF(hnd->lockState & private_handle_t::LOCK_STATE_READ_MASK, 132 "handle %p still locked (state=%08x)", 133 hnd, hnd->lockState); 134 135 // never unmap buffers that were created in this process 136 if (hnd->pid != getpid()) { 137 if (hnd->lockState & private_handle_t::LOCK_STATE_MAPPED) { 138 gralloc_unmap(module, handle); 139 } 140 hnd->base = 0; 141 hnd->lockState = 0; 142 hnd->writeOwner = 0; 143 } 144 return 0; 145} 146 147int gralloc_lock(gralloc_module_t const* module, 148 buffer_handle_t handle, int usage, 149 int l, int t, int w, int h, 150 void** vaddr) 151{ 152 if (private_handle_t::validate(handle) < 0) 153 return -EINVAL; 154 155 int err = 0; 156 private_handle_t* hnd = (private_handle_t*)handle; 157 int32_t current_value, new_value; 158 int retry; 159 160 do { 161 current_value = hnd->lockState; 162 new_value = current_value; 163 164 if (current_value & private_handle_t::LOCK_STATE_WRITE) { 165 // already locked for write 166 LOGE("handle %p already locked for write", handle); 167 return -EBUSY; 168 } else if (current_value & private_handle_t::LOCK_STATE_READ_MASK) { 169 // already locked for read 170 if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_HW_RENDER)) { 171 LOGE("handle %p already locked for read", handle); 172 return -EBUSY; 173 } else { 174 // this is not an error 175 //LOGD("%p already locked for read... count = %d", 176 // handle, (current_value & ~(1<<31))); 177 } 178 } 179 180 // not currently locked 181 if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_HW_RENDER)) { 182 // locking for write 183 new_value |= private_handle_t::LOCK_STATE_WRITE; 184 } 185 new_value++; 186 187 retry = android_atomic_cmpxchg(current_value, new_value, 188 (volatile int32_t*)&hnd->lockState); 189 } while (retry); 190 191 if (new_value & private_handle_t::LOCK_STATE_WRITE) { 192 // locking for write, store the tid 193 hnd->writeOwner = gettid(); 194 } 195 196 if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) { 197 if (!(current_value & private_handle_t::LOCK_STATE_MAPPED)) { 198 // we need to map for real 199 pthread_mutex_t* const lock = &sMapLock; 200 pthread_mutex_lock(lock); 201 if (!(hnd->lockState & private_handle_t::LOCK_STATE_MAPPED)) { 202 err = gralloc_map(module, handle, vaddr); 203 if (err == 0) { 204 android_atomic_or(private_handle_t::LOCK_STATE_MAPPED, 205 (volatile int32_t*)&(hnd->lockState)); 206 } 207 } 208 pthread_mutex_unlock(lock); 209 } 210 *vaddr = (void*)hnd->base; 211 } 212 213 return err; 214} 215 216int gralloc_unlock(gralloc_module_t const* module, 217 buffer_handle_t handle) 218{ 219 if (private_handle_t::validate(handle) < 0) 220 return -EINVAL; 221 222 private_handle_t* hnd = (private_handle_t*)handle; 223 int32_t current_value, new_value; 224 225 do { 226 current_value = hnd->lockState; 227 new_value = current_value; 228 229 if (current_value & private_handle_t::LOCK_STATE_WRITE) { 230 // locked for write 231 if (hnd->writeOwner == gettid()) { 232 hnd->writeOwner = 0; 233 new_value &= ~private_handle_t::LOCK_STATE_WRITE; 234 } 235 } 236 237 if ((new_value & private_handle_t::LOCK_STATE_READ_MASK) == 0) { 238 LOGE("handle %p not locked", handle); 239 return -EINVAL; 240 } 241 242 new_value--; 243 244 } while (android_atomic_cmpxchg(current_value, new_value, 245 (volatile int32_t*)&hnd->lockState)); 246 247 return 0; 248} 249