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             LOGE("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         //LOGD("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         //LOGD("unmapping from %p, size=%d", base, size);
     91         if (munmap(base, size) < 0) {
     92             LOGE("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     LOGE_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     LOGE_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             if (hnd->pid != getpid()) {
    176                 // ... unless it's a "master" pmem buffer, that is a buffer
    177                 // mapped in the process it's been allocated.
    178                 // (see gralloc_alloc_buffer())
    179                 gralloc_unmap(module, hnd);
    180             }
    181         } else {
    182             gralloc_unmap(module, hnd);
    183         }
    184     }
    185 
    186     return 0;
    187 }
    188 
    189 int gralloc_lock(gralloc_module_t const* module,
    190         buffer_handle_t handle, int usage,
    191         int l, int t, int w, int h,
    192         void** vaddr)
    193 {
    194     if (private_handle_t::validate(handle) < 0)
    195         return -EINVAL;
    196 
    197     int err = 0;
    198     private_handle_t* hnd = (private_handle_t*)handle;
    199     int32_t current_value, new_value;
    200     int retry;
    201 
    202     do {
    203         current_value = hnd->lockState;
    204         new_value = current_value;
    205 
    206         if (current_value & private_handle_t::LOCK_STATE_WRITE) {
    207             // already locked for write
    208             LOGE("handle %p already locked for write", handle);
    209             return -EBUSY;
    210         } else if (current_value & private_handle_t::LOCK_STATE_READ_MASK) {
    211             // already locked for read
    212             if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_HW_RENDER)) {
    213                 LOGE("handle %p already locked for read", handle);
    214                 return -EBUSY;
    215             } else {
    216                 // this is not an error
    217                 //LOGD("%p already locked for read... count = %d",
    218                 //        handle, (current_value & ~(1<<31)));
    219             }
    220         }
    221 
    222         // not currently locked
    223         if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_HW_RENDER)) {
    224             // locking for write
    225             new_value |= private_handle_t::LOCK_STATE_WRITE;
    226         }
    227         new_value++;
    228 
    229         retry = android_atomic_cmpxchg(current_value, new_value,
    230                 (volatile int32_t*)&hnd->lockState);
    231     } while (retry);
    232 
    233     if (new_value & private_handle_t::LOCK_STATE_WRITE) {
    234         // locking for write, store the tid
    235         hnd->writeOwner = gettid();
    236     }
    237 
    238     // if requesting sw write for non-framebuffer handles, flag for
    239     // flushing at unlock
    240     if ((usage & GRALLOC_USAGE_SW_WRITE_MASK) &&
    241         !(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
    242         hnd->flags |= private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
    243     }
    244 
    245     if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
    246         if (!(current_value & private_handle_t::LOCK_STATE_MAPPED)) {
    247             // we need to map for real
    248             pthread_mutex_t* const lock = &sMapLock;
    249             pthread_mutex_lock(lock);
    250             if (!(hnd->lockState & private_handle_t::LOCK_STATE_MAPPED)) {
    251                 err = gralloc_map(module, handle, vaddr);
    252                 if (err == 0) {
    253                     android_atomic_or(private_handle_t::LOCK_STATE_MAPPED,
    254                             (volatile int32_t*)&(hnd->lockState));
    255                 }
    256             }
    257             pthread_mutex_unlock(lock);
    258         }
    259         *vaddr = (void*)hnd->base;
    260     }
    261 
    262     return err;
    263 }
    264 
    265 int gralloc_unlock(gralloc_module_t const* module,
    266         buffer_handle_t handle)
    267 {
    268     if (private_handle_t::validate(handle) < 0)
    269         return -EINVAL;
    270 
    271     private_handle_t* hnd = (private_handle_t*)handle;
    272     int32_t current_value, new_value;
    273 
    274     if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) {
    275         struct pmem_region region;
    276         int err;
    277 
    278         region.offset = hnd->offset;
    279         region.len = hnd->size;
    280         err = ioctl(hnd->fd, PMEM_CACHE_FLUSH, &region);
    281         LOGE_IF(err < 0, "cannot flush handle %p (offs=%x len=%x)\n",
    282                 hnd, hnd->offset, hnd->size);
    283         hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
    284     }
    285 
    286     do {
    287         current_value = hnd->lockState;
    288         new_value = current_value;
    289 
    290         if (current_value & private_handle_t::LOCK_STATE_WRITE) {
    291             // locked for write
    292             if (hnd->writeOwner == gettid()) {
    293                 hnd->writeOwner = 0;
    294                 new_value &= ~private_handle_t::LOCK_STATE_WRITE;
    295             }
    296         }
    297 
    298         if ((new_value & private_handle_t::LOCK_STATE_READ_MASK) == 0) {
    299             LOGE("handle %p not locked", handle);
    300             return -EINVAL;
    301         }
    302 
    303         new_value--;
    304 
    305     } while (android_atomic_cmpxchg(current_value, new_value,
    306             (volatile int32_t*)&hnd->lockState));
    307 
    308     return 0;
    309 }
    310 
    311 /*****************************************************************************/
    312 
    313 int gralloc_perform(struct gralloc_module_t const* module,
    314         int operation, ... )
    315 {
    316     int res = -EINVAL;
    317     va_list args;
    318     va_start(args, operation);
    319 
    320     switch (operation) {
    321         case GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER: {
    322             int fd = va_arg(args, int);
    323             size_t size = va_arg(args, size_t);
    324             size_t offset = va_arg(args, size_t);
    325             void* base = va_arg(args, void*);
    326 
    327             // validate that it's indeed a pmem buffer
    328             pmem_region region;
    329             if (ioctl(fd, PMEM_GET_SIZE, &region) < 0) {
    330                 break;
    331             }
    332 
    333             native_handle_t** handle = va_arg(args, native_handle_t**);
    334             private_handle_t* hnd = (private_handle_t*)native_handle_create(
    335                     private_handle_t::sNumFds, private_handle_t::sNumInts);
    336             hnd->magic = private_handle_t::sMagic;
    337             hnd->fd = fd;
    338             hnd->flags = private_handle_t::PRIV_FLAGS_USES_PMEM;
    339             hnd->size = size;
    340             hnd->offset = offset;
    341             hnd->base = intptr_t(base) + offset;
    342             hnd->lockState = private_handle_t::LOCK_STATE_MAPPED;
    343             *handle = (native_handle_t *)hnd;
    344             res = 0;
    345             break;
    346         }
    347     }
    348 
    349     va_end(args);
    350     return res;
    351 }
    352