summaryrefslogtreecommitdiffstats
path: root/libsync/sync.c
diff options
context:
space:
mode:
Diffstat (limited to 'libsync/sync.c')
-rw-r--r--libsync/sync.c196
1 files changed, 158 insertions, 38 deletions
diff --git a/libsync/sync.c b/libsync/sync.c
index 9ed03dba8..27dab832f 100644
--- a/libsync/sync.c
+++ b/libsync/sync.c
@@ -27,8 +27,47 @@
#include <sys/stat.h>
#include <sys/types.h>
-#include <sync/sync.h>
+#include <android/sync.h>
+/* Legacy Sync API */
+
+struct sync_legacy_merge_data {
+ int32_t fd2;
+ char name[32];
+ int32_t fence;
+};
+
+/**
+ * DOC: SYNC_IOC_MERGE - merge two fences
+ *
+ * Takes a struct sync_merge_data. Creates a new fence containing copies of
+ * the sync_pts in both the calling fd and sync_merge_data.fd2. Returns the
+ * new fence's fd in sync_merge_data.fence
+ *
+ * This is the legacy version of the Sync API before the de-stage that happened
+ * on Linux kernel 4.7.
+ */
+#define SYNC_IOC_LEGACY_MERGE _IOWR(SYNC_IOC_MAGIC, 1, \
+ struct sync_legacy_merge_data)
+
+/**
+ * DOC: SYNC_IOC_LEGACY_FENCE_INFO - get detailed information on a fence
+ *
+ * Takes a struct sync_fence_info_data with extra space allocated for pt_info.
+ * Caller should write the size of the buffer into len. On return, len is
+ * updated to reflect the total size of the sync_fence_info_data including
+ * pt_info.
+ *
+ * pt_info is a buffer containing sync_pt_infos for every sync_pt in the fence.
+ * To iterate over the sync_pt_infos, use the sync_pt_info.len field.
+ *
+ * This is the legacy version of the Sync API before the de-stage that happened
+ * on Linux kernel 4.7.
+ */
+#define SYNC_IOC_LEGACY_FENCE_INFO _IOWR(SYNC_IOC_MAGIC, 2,\
+ struct sync_fence_info_data)
+
+/* SW Sync API */
struct sw_sync_create_fence_data {
__u32 value;
@@ -98,13 +137,11 @@ int sync_merge(const char *name, int fd1, int fd2)
return data.fence;
}
-struct sync_fence_info_data *sync_fence_info(int fd)
+static struct sync_fence_info_data *legacy_sync_fence_info(int fd)
{
struct sync_fence_info_data *legacy_info;
struct sync_pt_info *legacy_pt_info;
- struct sync_file_info *info;
- struct sync_fence_info *fence_info;
- int err, num_fences, i;
+ int err;
legacy_info = malloc(4096);
if (legacy_info == NULL)
@@ -112,46 +149,57 @@ struct sync_fence_info_data *sync_fence_info(int fd)
legacy_info->len = 4096;
err = ioctl(fd, SYNC_IOC_LEGACY_FENCE_INFO, legacy_info);
- if (err < 0 && errno != ENOTTY) {
+ if (err < 0) {
free(legacy_info);
return NULL;
- } else if (err == 0) {
- return legacy_info;
}
+ return legacy_info;
+}
- info = calloc(1, sizeof(*info));
- if (info == NULL)
- goto free;
+static struct sync_file_info *modern_sync_file_info(int fd)
+{
+ struct sync_file_info local_info;
+ struct sync_file_info *info;
+ int err;
- err = ioctl(fd, SYNC_IOC_FILE_INFO, info);
+ memset(&local_info, 0, sizeof(local_info));
+ err = ioctl(fd, SYNC_IOC_FILE_INFO, &local_info);
if (err < 0)
- goto free;
-
- num_fences = info->num_fences;
-
- if (num_fences) {
- info->flags = 0;
- info->num_fences = num_fences;
- info->sync_fence_info = (uint64_t) calloc(num_fences,
- sizeof(struct sync_fence_info));
- if ((void *)info->sync_fence_info == NULL)
- goto free;
-
- err = ioctl(fd, SYNC_IOC_FILE_INFO, info);
- if (err < 0) {
- free((void *)info->sync_fence_info);
- goto free;
- }
+ return NULL;
+
+ info = calloc(1, sizeof(struct sync_file_info) +
+ local_info.num_fences * sizeof(struct sync_fence_info));
+ if (!info)
+ return NULL;
+ info->sync_fence_info = (__u64)(uintptr_t)(info + 1);
+
+ err = ioctl(fd, SYNC_IOC_FILE_INFO, info);
+ if (err < 0) {
+ free(info);
+ return NULL;
}
+ return info;
+}
+
+static struct sync_fence_info_data *sync_file_info_to_legacy_fence_info(
+ const struct sync_file_info *info)
+{
+ struct sync_fence_info_data *legacy_info;
+ struct sync_pt_info *legacy_pt_info;
+ const struct sync_fence_info *fence_info = sync_get_fence_info(info);
+ const uint32_t num_fences = info->num_fences;
+
+ legacy_info = malloc(4096);
+ if (legacy_info == NULL)
+ return NULL;
legacy_info->len = sizeof(*legacy_info) +
- num_fences * sizeof(struct sync_fence_info);
+ num_fences * sizeof(struct sync_pt_info);
strlcpy(legacy_info->name, info->name, sizeof(legacy_info->name));
legacy_info->status = info->status;
legacy_pt_info = (struct sync_pt_info *)legacy_info->pt_info;
- fence_info = (struct sync_fence_info *)info->sync_fence_info;
- for (i = 0 ; i < num_fences ; i++) {
+ for (uint32_t i = 0; i < num_fences; i++) {
legacy_pt_info[i].len = sizeof(*legacy_pt_info);
strlcpy(legacy_pt_info[i].obj_name, fence_info[i].obj_name,
sizeof(legacy_pt_info->obj_name));
@@ -161,14 +209,81 @@ struct sync_fence_info_data *sync_fence_info(int fd)
legacy_pt_info[i].timestamp_ns = fence_info[i].timestamp_ns;
}
- free((void *)info->sync_fence_info);
- free(info);
return legacy_info;
+}
-free:
- free(legacy_info);
- free(info);
- return NULL;
+static struct sync_file_info* legacy_fence_info_to_sync_file_info(
+ struct sync_fence_info_data *legacy_info)
+{
+ struct sync_file_info *info;
+ struct sync_pt_info *pt;
+ struct sync_fence_info *fence;
+ size_t num_fences;
+ int err;
+
+ pt = NULL;
+ num_fences = 0;
+ while ((pt = sync_pt_info(legacy_info, pt)) != NULL)
+ num_fences++;
+
+ info = calloc(1, sizeof(struct sync_file_info) +
+ num_fences * sizeof(struct sync_fence_info));
+ if (!info) {
+ free(legacy_info);
+ return NULL;
+ }
+ info->sync_fence_info = (__u64)(uintptr_t)(info + 1);
+
+ strlcpy(info->name, legacy_info->name, sizeof(info->name));
+ info->status = legacy_info->status;
+ info->num_fences = num_fences;
+
+ pt = NULL;
+ fence = sync_get_fence_info(info);
+ while ((pt = sync_pt_info(legacy_info, pt)) != NULL) {
+ strlcpy(fence->obj_name, pt->obj_name, sizeof(fence->obj_name));
+ strlcpy(fence->driver_name, pt->driver_name,
+ sizeof(fence->driver_name));
+ fence->status = pt->status;
+ fence->timestamp_ns = pt->timestamp_ns;
+ fence++;
+ }
+
+ return info;
+}
+
+struct sync_fence_info_data *sync_fence_info(int fd)
+{
+ struct sync_fence_info_data *legacy_info;
+
+ legacy_info = legacy_sync_fence_info(fd);
+ if (legacy_info || errno != ENOTTY)
+ return legacy_info;
+
+ struct sync_file_info* file_info;
+ file_info = modern_sync_file_info(fd);
+ if (!file_info)
+ return NULL;
+ legacy_info = sync_file_info_to_legacy_fence_info(file_info);
+ sync_file_info_free(file_info);
+ return legacy_info;
+}
+
+struct sync_file_info* sync_file_info(int32_t fd)
+{
+ struct sync_file_info *info;
+ struct sync_fence_info_data *legacy_info;
+
+ info = modern_sync_file_info(fd);
+ if (info || errno != ENOTTY)
+ return info;
+
+ legacy_info = legacy_sync_fence_info(fd);
+ if (!legacy_info)
+ return NULL;
+ info = legacy_fence_info_to_sync_file_info(legacy_info);
+ sync_fence_info_free(legacy_info);
+ return info;
}
struct sync_pt_info *sync_pt_info(struct sync_fence_info_data *info,
@@ -190,6 +305,11 @@ void sync_fence_info_free(struct sync_fence_info_data *info)
free(info);
}
+void sync_file_info_free(struct sync_file_info *info)
+{
+ free(info);
+}
+
int sw_sync_timeline_create(void)
{