#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_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"
/* Path to the sync device file. */
-#define SYNC_DEVICE_PATH "/dev/sw_sync"
+#define SYNC_DEVICE_PATH "/sys/kernel/debug/sync/sw_sync"
/* Argument data structure for the timeline.create_fence ioctl. */
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) */
#define ERRNO_BUF_SIZE 256
+/* LCOV_EXCL_START */
static inline void
_log_errno()
{
char buf[ERRNO_BUF_SIZE];
if (strerror_r(errnum, buf, ERRNO_BUF_SIZE) == 0) {
- TBM_LOG_E("errno : %d(%s)\n", errnum, buf);
+ TBM_ERR("errno : %d(%s)\n", errnum, buf);
return;
} else {
- TBM_LOG_E("errno : %d()\n", errnum);
+ TBM_ERR("errno : %d()\n", errnum);
return;
}
}
{
tbm_fd timeline = open(SYNC_DEVICE_PATH, O_RDWR | O_CLOEXEC);
+ if (timeline < 0)
+ timeline = open(SYNC_DEVICE_PATH_LEGACY, O_RDWR | O_CLOEXEC);
+
if (timeline == -1)
_log_errno();
int
tbm_sync_fence_wait(tbm_fd fence, int timeout)
{
- __s32 arg = timeout;
- int ret;
-
- /* Retry while ioctl() ended up with interrupt. */
- do {
- ret = ioctl(fence, FENCE_IOC_WAIT, &arg);
- } while (ret == -1 && errno == EINTR);
+ struct pollfd fds;
+ int ret;
- /* 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;
}
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;
}
return data.fence;
}
+/* LCOV_EXCL_STOP */