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 if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_GPU) { 179 // XXX: for now do nothing here 180 } else { 181 gralloc_unmap(module, hnd); 182 } 183 } 184 185 return 0; 186 } 187 gralloc_lock(gralloc_module_t const * module,buffer_handle_t handle,int usage,int l,int t,int w,int h,void ** vaddr)188 int gralloc_lock(gralloc_module_t const* module, 189 buffer_handle_t handle, int usage, 190 int l, int t, int w, int h, 191 void** vaddr) 192 { 193 if (private_handle_t::validate(handle) < 0) 194 return -EINVAL; 195 196 int err = 0; 197 private_handle_t* hnd = (private_handle_t*)handle; 198 int32_t current_value, new_value; 199 int retry; 200 201 do { 202 current_value = hnd->lockState; 203 new_value = current_value; 204 205 if (current_value & private_handle_t::LOCK_STATE_WRITE) { 206 // already locked for write 207 LOGE("handle %p already locked for write", handle); 208 return -EBUSY; 209 } else if (current_value & private_handle_t::LOCK_STATE_READ_MASK) { 210 // already locked for read 211 if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_HW_RENDER)) { 212 LOGE("handle %p already locked for read", handle); 213 return -EBUSY; 214 } else { 215 // this is not an error 216 //LOGD("%p already locked for read... count = %d", 217 // handle, (current_value & ~(1<<31))); 218 } 219 } 220 221 // not currently locked 222 if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_HW_RENDER)) { 223 // locking for write 224 new_value |= private_handle_t::LOCK_STATE_WRITE; 225 } 226 new_value++; 227 228 retry = android_atomic_cmpxchg(current_value, new_value, 229 (volatile int32_t*)&hnd->lockState); 230 } while (retry); 231 232 if (new_value & private_handle_t::LOCK_STATE_WRITE) { 233 // locking for write, store the tid 234 hnd->writeOwner = gettid(); 235 } 236 237 if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) { 238 if (!(current_value & private_handle_t::LOCK_STATE_MAPPED)) { 239 // we need to map for real 240 pthread_mutex_t* const lock = &sMapLock; 241 pthread_mutex_lock(lock); 242 if (!(hnd->lockState & private_handle_t::LOCK_STATE_MAPPED)) { 243 err = gralloc_map(module, handle, vaddr); 244 if (err == 0) { 245 android_atomic_or(private_handle_t::LOCK_STATE_MAPPED, 246 (volatile int32_t*)&(hnd->lockState)); 247 } 248 } 249 pthread_mutex_unlock(lock); 250 } 251 *vaddr = (void*)hnd->base; 252 } 253 254 return err; 255 } 256 gralloc_unlock(gralloc_module_t const * module,buffer_handle_t handle)257 int gralloc_unlock(gralloc_module_t const* module, 258 buffer_handle_t handle) 259 { 260 if (private_handle_t::validate(handle) < 0) 261 return -EINVAL; 262 263 private_handle_t* hnd = (private_handle_t*)handle; 264 int32_t current_value, new_value; 265 266 do { 267 current_value = hnd->lockState; 268 new_value = current_value; 269 270 if (current_value & private_handle_t::LOCK_STATE_WRITE) { 271 // locked for write 272 if (hnd->writeOwner == gettid()) { 273 hnd->writeOwner = 0; 274 new_value &= ~private_handle_t::LOCK_STATE_WRITE; 275 } 276 } 277 278 if ((new_value & private_handle_t::LOCK_STATE_READ_MASK) == 0) { 279 LOGE("handle %p not locked", handle); 280 return -EINVAL; 281 } 282 283 new_value--; 284 285 } while (android_atomic_cmpxchg(current_value, new_value, 286 (volatile int32_t*)&hnd->lockState)); 287 288 return 0; 289 } 290 291 /*****************************************************************************/ 292 gralloc_perform(struct gralloc_module_t const * module,int operation,...)293 int gralloc_perform(struct gralloc_module_t const* module, 294 int operation, ... ) 295 { 296 int res = -EINVAL; 297 va_list args; 298 va_start(args, operation); 299 300 switch (operation) { 301 case GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER: { 302 int fd = va_arg(args, int); 303 size_t size = va_arg(args, size_t); 304 size_t offset = va_arg(args, size_t); 305 void* base = va_arg(args, void*); 306 native_handle_t** handle = va_arg(args, native_handle_t**); 307 private_handle_t* hnd = (private_handle_t*)native_handle_create( 308 private_handle_t::sNumFds, private_handle_t::sNumInts); 309 hnd->magic = private_handle_t::sMagic; 310 hnd->fd = fd; 311 hnd->flags = private_handle_t::PRIV_FLAGS_USES_PMEM; 312 hnd->size = size; 313 hnd->offset = offset; 314 hnd->base = intptr_t(base) + offset; 315 hnd->lockState = private_handle_t::LOCK_STATE_MAPPED; 316 *handle = (native_handle_t *)hnd; 317 res = 0; 318 break; 319 } 320 } 321 322 va_end(args); 323 return res; 324 } 325