Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Code Aurora Forum, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include <cutils/log.h>
- #include <cutils/native_handle.h>
- #include <gralloc_priv.h>
- #include <linux/genlock.h>
- #include <fcntl.h>
- #include <sys/ioctl.h>
- #include "genlock.h"
- #define GENLOCK_DEVICE "/dev/genlock"
- #ifndef USE_GENLOCK
- #define USE_GENLOCK
- #endif
- namespace {
- /* Internal function to map the userspace locks to the kernel lock types */
- int get_kernel_lock_type(genlock_lock_type lockType)
- {
- int kLockType = 0;
- // If the user sets both a read and write lock, higher preference is
- // given to the write lock.
- if (lockType & GENLOCK_WRITE_LOCK) {
- kLockType = GENLOCK_WRLOCK;
- } else if (lockType & GENLOCK_READ_LOCK) {
- kLockType = GENLOCK_RDLOCK;
- } else {
- ALOGE("%s: invalid lockType (lockType = %d)",
- __FUNCTION__, lockType);
- return -1;
- }
- return kLockType;
- }
- /* Internal function to perform the actual lock/unlock operations */
- genlock_status_t perform_lock_unlock_operation(native_handle_t *buffer_handle,
- int lockType, int timeout,
- int flags)
- {
- if (private_handle_t::validate(buffer_handle)) {
- ALOGE("%s: handle is invalid", __FUNCTION__);
- return GENLOCK_FAILURE;
- }
- private_handle_t *hnd = reinterpret_cast<private_handle_t*>
- (buffer_handle);
- if ((hnd->flags & private_handle_t::PRIV_FLAGS_UNSYNCHRONIZED) == 0) {
- if (hnd->genlockPrivFd < 0) {
- ALOGE("%s: the lock has not been created,"
- "or has not been attached", __FUNCTION__);
- return GENLOCK_FAILURE;
- }
- genlock_lock lock;
- lock.op = lockType;
- lock.flags = flags;
- lock.timeout = timeout;
- lock.fd = hnd->genlockHandle;
- #ifdef GENLOCK_IOC_DREADLOCK
- if (ioctl(hnd->genlockPrivFd, GENLOCK_IOC_DREADLOCK, &lock)) {
- ALOGE("%s: GENLOCK_IOC_DREADLOCK failed (lockType0x%x,"
- "err=%s fd=%d)", __FUNCTION__,
- lockType, strerror(errno), hnd->fd);
- if (ETIMEDOUT == errno)
- return GENLOCK_TIMEDOUT;
- return GENLOCK_FAILURE;
- }
- #else
- // depreciated
- if (ioctl(hnd->genlockPrivFd, GENLOCK_IOC_LOCK, &lock)) {
- ALOGE("%s: GENLOCK_IOC_LOCK failed (lockType0x%x, err=%s fd=%d)"
- ,__FUNCTION__, lockType, strerror(errno), hnd->fd);
- if (ETIMEDOUT == errno)
- return GENLOCK_TIMEDOUT;
- return GENLOCK_FAILURE;
- }
- #endif
- }
- return GENLOCK_NO_ERROR;
- }
- /* Internal function to close the fd and release the handle */
- void close_genlock_fd_and_handle(int& fd, int& handle)
- {
- if (fd >=0 ) {
- close(fd);
- fd = -1;
- }
- if (handle >= 0) {
- close(handle);
- handle = -1;
- }
- }
- }
- /*
- * Create a genlock lock. The genlock lock file descriptor and the lock
- * handle are stored in the buffer_handle.
- *
- * @param: handle of the buffer
- * @return error status.
- */
- genlock_status_t genlock_create_lock(native_handle_t *buffer_handle)
- {
- genlock_status_t ret = GENLOCK_NO_ERROR;
- if (private_handle_t::validate(buffer_handle)) {
- ALOGE("%s: handle is invalid", __FUNCTION__);
- return GENLOCK_FAILURE;
- }
- private_handle_t *hnd = reinterpret_cast<private_handle_t*>(buffer_handle);
- #ifdef USE_GENLOCK
- if ((hnd->flags & private_handle_t::PRIV_FLAGS_UNSYNCHRONIZED) == 0) {
- // Open the genlock device
- int fd = open(GENLOCK_DEVICE, O_RDWR);
- if (fd < 0) {
- ALOGE("%s: open genlock device failed (err=%s)", __FUNCTION__,
- strerror(errno));
- return GENLOCK_FAILURE;
- }
- // Create a new lock
- genlock_lock lock;
- if (ioctl(fd, GENLOCK_IOC_NEW, NULL)) {
- ALOGE("%s: GENLOCK_IOC_NEW failed (error=%s)", __FUNCTION__,
- strerror(errno));
- close_genlock_fd_and_handle(fd, lock.fd);
- ret = GENLOCK_FAILURE;
- }
- // Export the lock for other processes to be able to use it.
- if (GENLOCK_FAILURE != ret) {
- if (ioctl(fd, GENLOCK_IOC_EXPORT, &lock)) {
- ALOGE("%s: GENLOCK_IOC_EXPORT failed (error=%s)", __FUNCTION__,
- strerror(errno));
- close_genlock_fd_and_handle(fd, lock.fd);
- ret = GENLOCK_FAILURE;
- }
- }
- // Store the lock params in the handle.
- hnd->genlockPrivFd = fd;
- hnd->genlockHandle = lock.fd;
- } else {
- hnd->genlockHandle = 0;
- }
- #else
- hnd->genlockHandle = 0;
- #endif
- return ret;
- }
- /*
- * Release a genlock lock associated with the handle.
- *
- * @param: handle of the buffer
- * @return error status.
- */
- genlock_status_t genlock_release_lock(native_handle_t *buffer_handle)
- {
- genlock_status_t ret = GENLOCK_NO_ERROR;
- #ifdef USE_GENLOCK
- if (private_handle_t::validate(buffer_handle)) {
- ALOGE("%s: handle is invalid", __FUNCTION__);
- return GENLOCK_FAILURE;
- }
- private_handle_t *hnd = reinterpret_cast<private_handle_t*>(buffer_handle);
- if ((hnd->flags & private_handle_t::PRIV_FLAGS_UNSYNCHRONIZED) == 0) {
- if (hnd->genlockPrivFd < 0) {
- ALOGE("%s: the lock is invalid", __FUNCTION__);
- return GENLOCK_FAILURE;
- }
- // Close the fd and reset the parameters.
- close_genlock_fd_and_handle(hnd->genlockPrivFd, hnd->genlockHandle);
- }
- #endif
- return ret;
- }
- /*
- * Attach a lock to the buffer handle passed via an IPC.
- *
- * @param: handle of the buffer
- * @return error status.
- */
- genlock_status_t genlock_attach_lock(native_handle_t *buffer_handle)
- {
- genlock_status_t ret = GENLOCK_NO_ERROR;
- #ifdef USE_GENLOCK
- if (private_handle_t::validate(buffer_handle)) {
- ALOGE("%s: handle is invalid", __FUNCTION__);
- return GENLOCK_FAILURE;
- }
- private_handle_t *hnd = reinterpret_cast<private_handle_t*>(buffer_handle);
- if ((hnd->flags & private_handle_t::PRIV_FLAGS_UNSYNCHRONIZED) == 0) {
- // Open the genlock device
- int fd = open(GENLOCK_DEVICE, O_RDWR);
- if (fd < 0) {
- ALOGE("%s: open genlock device failed (err=%s)", __FUNCTION__,
- strerror(errno));
- return GENLOCK_FAILURE;
- }
- // Attach the local handle to an existing lock
- genlock_lock lock;
- lock.fd = hnd->genlockHandle;
- if (ioctl(fd, GENLOCK_IOC_ATTACH, &lock)) {
- ALOGE("%s: GENLOCK_IOC_ATTACH failed (err=%s)", __FUNCTION__,
- strerror(errno));
- close_genlock_fd_and_handle(fd, lock.fd);
- ret = GENLOCK_FAILURE;
- }
- // Store the relavant information in the handle
- hnd->genlockPrivFd = fd;
- }
- #endif
- return ret;
- }
- /*
- * Lock the buffer specified by the buffer handle. The lock held by the buffer
- * is specified by the lockType. This function will block if a write lock is
- * requested on the buffer which has previously been locked for a read or write
- * operation. A buffer can be locked by multiple clients for read. An optional
- * timeout value can be specified. By default, there is no timeout.
- *
- * @param: handle of the buffer
- * @param: type of lock to be acquired by the buffer.
- * @param: timeout value in ms. GENLOCK_MAX_TIMEOUT is the maximum timeout value.
- * @return error status.
- */
- genlock_status_t genlock_lock_buffer(native_handle_t *buffer_handle,
- genlock_lock_type_t lockType,
- int timeout)
- {
- genlock_status_t ret = GENLOCK_NO_ERROR;
- #ifdef USE_GENLOCK
- // Translate the locktype
- int kLockType = get_kernel_lock_type(lockType);
- if (-1 == kLockType) {
- ALOGE("%s: invalid lockType", __FUNCTION__);
- return GENLOCK_FAILURE;
- }
- if (0 == timeout) {
- ALOGW("%s: trying to lock a buffer with timeout = 0", __FUNCTION__);
- }
- // Call the private function to perform the lock operation specified.
- ret = perform_lock_unlock_operation(buffer_handle, kLockType, timeout, 0);
- #endif
- return ret;
- }
- /*
- * Unlocks a buffer that has previously been locked by the client.
- *
- * @param: handle of the buffer to be unlocked.
- * @return: error status.
- */
- genlock_status_t genlock_unlock_buffer(native_handle_t *buffer_handle)
- {
- genlock_status_t ret = GENLOCK_NO_ERROR;
- #ifdef USE_GENLOCK
- // Do the unlock operation by setting the unlock flag. Timeout is always
- // 0 in this case.
- ret = perform_lock_unlock_operation(buffer_handle, GENLOCK_UNLOCK, 0, 0);
- #endif
- return ret;
- }
- /*
- * Blocks the calling process until the lock held on the handle is unlocked.
- *
- * @param: handle of the buffer
- * @param: timeout value for the wait.
- * return: error status.
- */
- genlock_status_t genlock_wait(native_handle_t *buffer_handle, int timeout) {
- #ifdef USE_GENLOCK
- if (private_handle_t::validate(buffer_handle)) {
- ALOGE("%s: handle is invalid", __FUNCTION__);
- return GENLOCK_FAILURE;
- }
- private_handle_t *hnd = reinterpret_cast<private_handle_t*>(buffer_handle);
- if ((hnd->flags & private_handle_t::PRIV_FLAGS_UNSYNCHRONIZED) == 0) {
- if (hnd->genlockPrivFd < 0) {
- ALOGE("%s: the lock is invalid", __FUNCTION__);
- return GENLOCK_FAILURE;
- }
- if (0 == timeout)
- ALOGW("%s: timeout = 0", __FUNCTION__);
- genlock_lock lock;
- lock.fd = hnd->genlockHandle;
- lock.timeout = timeout;
- if (ioctl(hnd->genlockPrivFd, GENLOCK_IOC_WAIT, &lock)) {
- ALOGE("%s: GENLOCK_IOC_WAIT failed (err=%s)", __FUNCTION__,
- strerror(errno));
- return GENLOCK_FAILURE;
- }
- }
- #endif
- return GENLOCK_NO_ERROR;
- }
- /*
- * Convert a write lock that we own to a read lock
- *
- * @param: handle of the buffer
- * @param: timeout value for the wait.
- * return: error status.
- */
- genlock_status_t genlock_write_to_read(native_handle_t *buffer_handle,
- int timeout) {
- genlock_status_t ret = GENLOCK_NO_ERROR;
- #ifdef USE_GENLOCK
- if (0 == timeout) {
- ALOGW("%s: trying to lock a buffer with timeout = 0", __FUNCTION__);
- }
- // Call the private function to perform the lock operation specified.
- #ifdef GENLOCK_IOC_DREADLOCK
- ret = perform_lock_unlock_operation(buffer_handle, GENLOCK_RDLOCK, timeout,
- GENLOCK_WRITE_TO_READ);
- #else
- // depreciated
- ret = perform_lock_unlock_operation(buffer_handle, GENLOCK_RDLOCK,
- timeout, 0);
- #endif
- #endif
- return ret;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement