tbm_sync: support mainline interface of fence 81/220581/3
authorChangyeon Lee <cyeon.lee@samsung.com>
Thu, 19 Dec 2019 12:44:38 +0000 (21:44 +0900)
committerChangyeon Lee <cyeon.lee@samsung.com>
Tue, 24 Dec 2019 04:32:21 +0000 (13:32 +0900)
1. first try to call maline FENCE_MERGE ioctl in tbm_sync_fence_merge.
2. use poll instead of legacy FENCE_WAIT ioctl in tbm_sync_fence_wait.

Change-Id: I636a99b4f49806c2a6519e44e2675b53ea83d3a5

src/tbm_sync.c

index 49d0266..d4bcd66 100644 (file)
@@ -40,6 +40,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include <errno.h>
 #include <sys/ioctl.h>
 #include <linux/types.h>
+#include <poll.h>
 
 /* IOCTLs for timeline file object. */
 #define TIMELINE_IOC_MAGIC                     'W'
@@ -47,9 +48,11 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define TIMELINE_IOC_INC                       _IOW(TIMELINE_IOC_MAGIC, 1, __u32)
 
 /* IOCTLs for fence file object. */
-#define FENCE_IOC_MAGIC                '>'
-#define FENCE_IOC_WAIT         _IOW(FENCE_IOC_MAGIC, 0, __s32)
-#define FENCE_IOC_MERGE                _IOWR(FENCE_IOC_MAGIC, 1, struct sync_merge_data)
+#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"
@@ -66,6 +69,15 @@ struct create_fence_data {
 
 /* 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) */
@@ -154,23 +166,29 @@ tbm_sync_fence_create(tbm_fd timeline, const char *name, unsigned int value)
 int
 tbm_sync_fence_wait(tbm_fd fence, int timeout)
 {
-       __s32   arg = timeout;
-       int             ret;
+       struct pollfd fds;
+       int ret;
 
-       /* Retry while ioctl() ended up with interrupt. */
-       do {
-               ret = ioctl(fence, FENCE_IOC_WAIT, &arg);
-       } while (ret == -1 && errno == EINTR);
-
-       /* ioctl() was successful. */
-       if (ret == 0)
-               return 1;
+       fds.fd = fence;
+       fds.events = POLLIN;
 
-       /* ioctl() ended up with timeout. */
-       if (errno == ETIME)
-               return -1;
+       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));
 
-       /* ioctl() failed for some reason. */
        _log_errno();
        return 0;
 }
@@ -179,10 +197,22 @@ tbm_fd
 tbm_sync_fence_merge(const char *name, tbm_fd fence1, tbm_fd fence2)
 {
        struct sync_merge_data data = { .fd2 = fence2 };
+       int ret;
 
        _copy_string(data.name, name, 32);
 
-       if (ioctl(fence1, FENCE_IOC_MERGE, &data) == -1) {
+       ret = ioctl(fence1, FENCE_IOC_MERGE, &data);
+       if (ret < 0 && errno == ENOTTY) {
+               struct sync_legacy_merge_data legacy_data = {. fd2 = fence2 };
+
+               _copy_string(legacy_data.name, name, 32);
+
+               ret = ioctl(fence1, FENCE_IOC_LEGACY_MERGE, &legacy_data);
+               if (ret < 0) {
+                       _log_errno();
+                       return -1;
+               }
+       } else if (ret < 0) {
                _log_errno();
                return -1;
        }