#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"
/* 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) */
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;
}
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;
}