tbm_sync: support mainline interface of fence
[platform/core/uifw/libtbm.git] / src / tbm_sync.c
index 569f69f..d4bcd66 100644 (file)
@@ -5,7 +5,7 @@ libtbm
 Copyright 2012 - 2016 Samsung Electronics co., Ltd. All Rights Reserved.
 
 Contact: SooChan Lim <sc1.lim@samsung.com>,
-         Changyeon Lee <cyeon.lee@samsung.com>,
+                Changyeon Lee <cyeon.lee@samsung.com>,
                 Boram Park <boram1288.park@samsung.com>,
                 Sangjin Lee <lsj119@samsung.com>
 
@@ -31,296 +31,192 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 **************************************************************************/
 
-#include "tbm_bufmgr.h"
+#include "config.h"
+
 #include "tbm_bufmgr_int.h"
 #include "tbm_sync.h"
 
-static pthread_mutex_t tbm_sync_lock;
-static int tbm_sync_support = 0;
-
-static bool
-_tbm_sync_mutex_init(void)
+#include <string.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <linux/types.h>
+#include <poll.h>
+
+/* IOCTLs for timeline file object. */
+#define TIMELINE_IOC_MAGIC                     'W'
+#define TIMELINE_IOC_CREATE_FENCE      _IOWR(TIMELINE_IOC_MAGIC, 0, struct create_fence_data)
+#define TIMELINE_IOC_INC                       _IOW(TIMELINE_IOC_MAGIC, 1, __u32)
+
+/* IOCTLs for fence file object. */
+#define FENCE_IOC_MAGIC                                '>'
+#define FENCE_IOC_MERGE                                _IOWR(FENCE_IOC_MAGIC, 3, struct sync_merge_data)
+
+#define FENCE_IOC_LEGACY_WAIT          _IOW(FENCE_IOC_MAGIC, 0, __s32)
+#define FENCE_IOC_LEGACY_MERGE         _IOWR(FENCE_IOC_MAGIC, 1, struct sync_legacy_merge_data)
+
+/* Path to the sync device legacy file. */
+#define SYNC_DEVICE_PATH_LEGACY        "/dev/sw_sync"
+
+/* Path to the sync device file. */
+#define SYNC_DEVICE_PATH       "/sys/kernel/debug/sync/sw_sync"
+
+/* Argument data structure for the timeline.create_fence ioctl. */
+struct create_fence_data {
+       __u32   value;          /* Pt value on the timeline for the fence (IN) */
+       char    name[32];       /* Name of the fence object (IN) */
+       __s32   fence;          /* File descriptor for the created fence (OUT) */
+};
+
+/* Argument data structure for the fence.merge ioctl. */
+struct sync_merge_data {
+       char    name[32];       /* Name of the new fence object (IN) */
+       __s32   fd2;            /* fence to merged with the fence (IN) */
+       __s32   fence;          /* File descriptor for the new fence (OUT) */
+       __u32   flags;          /* merge_data flags (IN) */
+       __u32   pad;            /* padding for 64-bit alignment, should always be zero */
+};
+
+/* Argument data structure for the legacy fence.merge ioctl. */
+struct sync_legacy_merge_data {
+       __s32   fd2;            /* fence to merged with the fence (IN) */
+       char    name[32];       /* Name of the new fence object (IN) */
+       __s32   fence;          /* File descriptor for the new fence (OUT) */
+};
+
+#define ERRNO_BUF_SIZE 256
+
+/* LCOV_EXCL_START */
+static inline void
+_log_errno()
 {
-       static bool tbm_sync_mutex_init = false;
-
-       if (tbm_sync_mutex_init)
-               return true;
+       /* calling strerror_r() might overwrite errno, so save it. */
+       int             errnum = errno;
+       char    buf[ERRNO_BUF_SIZE];
 
-       if (pthread_mutex_init(&tbm_sync_lock, NULL)) {
-               TBM_LOG_E("fail: tbm_sync mutex init\n");
-               return false;
+       if (strerror_r(errnum, buf, ERRNO_BUF_SIZE) == 0) {
+               TBM_ERR("errno : %d(%s)\n", errnum, buf);
+               return;
+       } else {
+               TBM_ERR("errno : %d()\n", errnum);
+               return;
        }
-
-       tbm_sync_mutex_init = true;
-
-       return true;
 }
 
-static void
-_tbm_sync_mutex_lock(void)
+static inline void
+_copy_string(char *dst, const char *src, size_t size)
 {
-       if (!_tbm_sync_mutex_init())
+       if (size == 0)
                return;
 
-       pthread_mutex_lock(&tbm_sync_lock);
-}
-
-static void
-_tbm_sync_mutex_unlock(void)
-{
-       pthread_mutex_unlock(&tbm_sync_lock);
-}
-
-static tbm_sync_error_e
-_tbm_sync_check_capability(void)
-{
-       tbm_bufmgr bufmgr = NULL;
-       unsigned int capabilities = TBM_BUFMGR_CAPABILITY_NONE;
-
-    if (tbm_sync_support)
-               return TBM_SYNC_ERROR_NONE;
-
-       /* check the bufmgr */
-       bufmgr = _tbm_bufmgr_get_bufmgr();
-       if (!bufmgr) {
-               return TBM_SYNC_ERROR_INVALID_OPERATION;
+       if (src == NULL || size == 1) {
+               *dst = '\0';
+               return;
        }
 
-       /* check the tbm_sync capability */
-       capabilities = tbm_bufmgr_get_capability(bufmgr);
-       if ((capabilities&TBM_BUFMGR_CAPABILITY_TBM_SYNC) != TBM_BUFMGR_CAPABILITY_TBM_SYNC) {
-               //TODO: check the sw_sync device node... to verify the timeline sync
-               tbm_sync_support = 1;
-
-               return TBM_SYNC_ERROR_INVALID_OPERATION;
+       while (size-- != 1) {
+               if ((*dst++ = *src++) == '\0')
+                       return;
        }
 
-       return TBM_SYNC_ERROR_NONE;
+       *dst = '\0';
 }
 
-tbm_sync_timeline_h
-tbm_sync_timeline_create(tbm_sync_error_e *error)
+tbm_fd
+tbm_sync_timeline_create(void)
 {
-       tbm_sync_error_e ret = TBM_SYNC_ERROR_NONE;
-       tbm_sync_timeline_h timeline = NULL;
-
-       _tbm_sync_mutex_lock();
-
-       /* check the tbm_sync capability */
-       ret = _tbm_sync_check_capability();;
-       if (ret != TBM_SYNC_ERROR_NONE)
-               goto done;
-
-       /* TODO: sync_timeline_create */
-
+       tbm_fd timeline = open(SYNC_DEVICE_PATH, O_RDWR | O_CLOEXEC);
 
-done:
-       if (error)
-               *error = ret;
+       if (timeline < 0)
+               timeline = open(SYNC_DEVICE_PATH_LEGACY, O_RDWR | O_CLOEXEC);
 
-       _tbm_sync_mutex_unlock();
+       if (timeline == -1)
+               _log_errno();
 
        return timeline;
 }
 
-tbm_sync_error_e
-tbm_sync_timeline_destroy(tbm_sync_timeline_h timeline)
-{
-       tbm_sync_error_e ret = TBM_SYNC_ERROR_NONE;
-
-       _tbm_sync_mutex_lock();
-
-       /* check the tbm_sync capability */
-       ret = _tbm_sync_check_capability();;
-       if (ret != TBM_SYNC_ERROR_NONE)
-               goto done;
-
-       /* TODO: sync_timeline_destroy */
-
-
-done:
-       _tbm_sync_mutex_unlock();
-
-    return ret;
-}
-
-tbm_sync_timeline_h
-tbm_sync_timeline_import(tbm_fd fd, tbm_sync_error_e *error)
-{
-       tbm_sync_error_e ret = TBM_SYNC_ERROR_NONE;
-       tbm_sync_timeline_h timeline = NULL;
-
-       _tbm_sync_mutex_lock();
-
-       /* check the tbm_sync capability */
-       ret = _tbm_sync_check_capability();;
-       if (ret != TBM_SYNC_ERROR_NONE)
-               goto done;
-
-       /* TODO: sync_timeline_import */
-
-done:
-       if (error)
-               *error = ret;
-
-       _tbm_sync_mutex_unlock();
-
-       return timeline;
-}
-
-tbm_sync_error_e
-tbm_sync_timeline_increase_count(tbm_sync_timeline_h timeline, unsigned int interval)
-{
-       tbm_sync_error_e ret = TBM_SYNC_ERROR_NONE;
-
-       _tbm_sync_mutex_lock();
-
-       /* check the tbm_sync capability */
-       ret = _tbm_sync_check_capability();;
-       if (ret != TBM_SYNC_ERROR_NONE)
-               goto done;
-
-       /* TODO: sync_timeline_increase_count */
-
-done:
-       _tbm_sync_mutex_unlock();
-
-       return ret;
-}
-
-unsigned int
-tbm_sync_timeline_get_cur_count(tbm_sync_timeline_h timeline, tbm_sync_error_e *error)
+int
+tbm_sync_timeline_inc(tbm_fd timeline, unsigned int count)
 {
-       tbm_sync_error_e ret = TBM_SYNC_ERROR_NONE;
-       unsigned int cur_count = 0;
-
-       _tbm_sync_mutex_lock();
-
-       /* check the tbm_sync capability */
-       ret = _tbm_sync_check_capability();;
-       if (ret != TBM_SYNC_ERROR_NONE)
-               goto done;
-
-       /* TODO: sync_timeline_get_cur_count */
-
-done:
-       if (error)
-               *error = ret;
-
-       _tbm_sync_mutex_unlock();
-
-       return cur_count;
-}
-
-tbm_sync_fence_h
-tbm_sync_fence_create(tbm_sync_timeline_h timeline, const char *name, unsigned int count_val, tbm_sync_error_e *error)
-{
-       tbm_sync_error_e ret = TBM_SYNC_ERROR_NONE;
-       tbm_sync_fence_h fence = NULL;
-
-       _tbm_sync_mutex_lock();
-
-       /* check the tbm_sync capability */
-       ret = _tbm_sync_check_capability();;
-       if (ret != TBM_SYNC_ERROR_NONE)
-               goto done;
-
-       /* TODO: sync_fence_create */
-
-done:
-       if (error)
-               *error = ret;
-
-       _tbm_sync_mutex_unlock();
+       __u32 arg = count;
 
-       return fence;
-}
-
-tbm_sync_error_e
-tbm_sync_fence_destroy(tbm_sync_fence_h fence)
-{
-       tbm_sync_error_e ret = TBM_SYNC_ERROR_NONE;
-
-       _tbm_sync_mutex_lock();
-
-       /* check the tbm_sync capability */
-       ret = _tbm_sync_check_capability();;
-       if (ret != TBM_SYNC_ERROR_NONE)
-               goto done;
-
-       /* TODO: sync_fence_destroy */
-
-done:
-       _tbm_sync_mutex_unlock();
+       if (ioctl(timeline, TIMELINE_IOC_INC, &arg) == -1) {
+               _log_errno();
+               return 0;
+       }
 
-       return ret;
+       return 1;
 }
 
-tbm_sync_error_e
-tbm_sync_fence_wait(tbm_sync_fence_h fence, int timeout)
+tbm_fd
+tbm_sync_fence_create(tbm_fd timeline, const char *name, unsigned int value)
 {
-       tbm_sync_error_e ret = TBM_SYNC_ERROR_NONE;
-
-       _tbm_sync_mutex_lock();
-
-       /* check the tbm_sync capability */
-       ret = _tbm_sync_check_capability();;
-       if (ret != TBM_SYNC_ERROR_NONE)
-               goto done;
+       struct create_fence_data data = { .value = value };
 
-       /* TODO: sync_fence_wait */
+       _copy_string(data.name, name, 32);
 
-done:
-       _tbm_sync_mutex_unlock();
+       if (ioctl(timeline, TIMELINE_IOC_CREATE_FENCE, &data) == -1) {
+               _log_errno();
+               return -1;
+       }
 
-       return ret;
+       return data.fence;
 }
 
-tbm_sync_fence_h
-tbm_sync_fence_merge(tbm_sync_fence_h fence1, tbm_sync_fence_h fence2, const char *name, tbm_sync_error_e *error)
+int
+tbm_sync_fence_wait(tbm_fd fence, int timeout)
 {
-       tbm_sync_error_e ret = TBM_SYNC_ERROR_NONE;
-       tbm_sync_fence_h fence = NULL;
-
-       _tbm_sync_mutex_lock();
-
-       /* check the tbm_sync capability */
-       ret = _tbm_sync_check_capability();;
-       if (ret != TBM_SYNC_ERROR_NONE)
-               goto done;
-
-       /* TODO: tbm_sync_fence_merge */
-
-done:
-       if (error)
-               *error = ret;
-
-       _tbm_sync_mutex_unlock();
-
-       return fence;
+       struct pollfd fds;
+       int ret;
+
+       fds.fd = fence;
+       fds.events = POLLIN;
+
+       do {
+               ret = poll(&fds, 1, timeout);
+               if (ret > 0) {
+                       if (fds.revents & (POLLERR | POLLNVAL)) {
+                               errno = EINVAL;
+                               _log_errno();
+                               return 0;
+                       }
+
+                       return 1;
+               } else if (ret == 0) {
+                       errno = ETIME;
+                       _log_errno();
+                       return 0;
+               }
+       } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
+
+       _log_errno();
+       return 0;
 }
 
-unsigned int
-tbm_sync_fence_get_count_val(tbm_sync_fence_h fence, tbm_sync_error_e *error)
+tbm_fd
+tbm_sync_fence_merge(const char *name, tbm_fd fence1, tbm_fd fence2)
 {
-       tbm_sync_error_e ret = TBM_SYNC_ERROR_NONE;
-       unsigned int count_val = 0;
-
-       _tbm_sync_mutex_lock();
+       struct sync_merge_data data = { .fd2 = fence2 };
+       int ret;
 
-       /* check the tbm_sync capability */
-       ret = _tbm_sync_check_capability();;
-       if (ret != TBM_SYNC_ERROR_NONE)
-               goto done;
+       _copy_string(data.name, name, 32);
 
-       /* TODO: sync_fence_get_count_val */
+       ret = ioctl(fence1, FENCE_IOC_MERGE, &data);
+       if (ret < 0 && errno == ENOTTY) {
+               struct sync_legacy_merge_data legacy_data = {. fd2 = fence2 };
 
-done:
-       if (error)
-               *error = ret;
+               _copy_string(legacy_data.name, name, 32);
 
-       _tbm_sync_mutex_unlock();
+               ret = ioctl(fence1, FENCE_IOC_LEGACY_MERGE, &legacy_data);
+               if (ret < 0) {
+                       _log_errno();
+                       return -1;
+               }
+       } else if (ret < 0) {
+               _log_errno();
+               return -1;
+       }
 
-       return count_val;
+       return data.fence;
 }
-
+/* LCOV_EXCL_STOP */