Home | History | Annotate | Download | only in libgralloc-qsd8k
      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>
     47 pid_t gettid() { return syscall(__NR_gettid);}
     48 #undef __KERNEL__
     49 #endif
     50 
     51 /*****************************************************************************/
     52 
     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 
     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 
    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 
    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 
    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 
    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 
    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, &region);
    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 
    320 int gralloc_perform(struct gralloc_module_t const* module,
    321         int operation, ... )
    322 {
    323     int res = -EINVAL;
    324     return res;
    325 }
    326