Merge changes Icb8e6290,Iadde7b21,I743ab92c,Ie078fbc2,I2ab3cd46, ...
* changes: libsync: tests: redefine PollOnDestroyedTimeline() libsync: tests: remove WaitOnDestroyedTimeline test libsync: add support to new Sync API libsync: open new location of sw_sync file libsync: add new Sync kernel API libsync: move kernel headers for sync ioctls to sync.h
This commit is contained in:
commit
c42bd0931f
|
@ -22,9 +22,16 @@
|
|||
#include <sys/cdefs.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
// XXX: These structs are copied from the header "linux/sync.h".
|
||||
struct sync_legacy_merge_data {
|
||||
int32_t fd2;
|
||||
char name[32];
|
||||
int32_t fence;
|
||||
};
|
||||
|
||||
struct sync_fence_info_data {
|
||||
uint32_t len;
|
||||
char name[32];
|
||||
|
@ -41,6 +48,108 @@ struct sync_pt_info {
|
|||
uint8_t driver_data[0];
|
||||
};
|
||||
|
||||
#define SYNC_IOC_MAGIC '>'
|
||||
|
||||
/**
|
||||
* DOC: SYNC_IOC_LEGACY_WAIT - wait for a fence to signal
|
||||
*
|
||||
* pass timeout in milliseconds. Waits indefinitely timeout < 0.
|
||||
*
|
||||
* This is the legacy version of the Sync API before the de-stage that happened
|
||||
* on Linux kernel 4.7.
|
||||
*/
|
||||
#define SYNC_IOC_LEGACY_WAIT _IOW(SYNC_IOC_MAGIC, 0, __s32)
|
||||
|
||||
/**
|
||||
* 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)
|
||||
|
||||
struct sync_merge_data {
|
||||
char name[32];
|
||||
int32_t fd2;
|
||||
int32_t fence;
|
||||
uint32_t flags;
|
||||
uint32_t pad;
|
||||
};
|
||||
|
||||
struct sync_file_info {
|
||||
char name[32];
|
||||
int32_t status;
|
||||
uint32_t flags;
|
||||
uint32_t num_fences;
|
||||
uint32_t pad;
|
||||
|
||||
uint64_t sync_fence_info;
|
||||
};
|
||||
|
||||
struct sync_fence_info {
|
||||
char obj_name[32];
|
||||
char driver_name[32];
|
||||
int32_t status;
|
||||
uint32_t flags;
|
||||
uint64_t timestamp_ns;
|
||||
};
|
||||
|
||||
/**
|
||||
* Mainline API:
|
||||
*
|
||||
* Opcodes 0, 1 and 2 were burned during a API change to avoid users of the
|
||||
* old API to get weird errors when trying to handling sync_files. The API
|
||||
* change happened during the de-stage of the Sync Framework when there was
|
||||
* no upstream users available.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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 new version of the Sync API after the de-stage that happened
|
||||
* on Linux kernel 4.7.
|
||||
*/
|
||||
#define SYNC_IOC_MERGE _IOWR(SYNC_IOC_MAGIC, 3, struct sync_merge_data)
|
||||
|
||||
/**
|
||||
* DOC: SYNC_IOC_FILE_INFO - get detailed information on a sync_file
|
||||
*
|
||||
* Takes a struct sync_file_info. If num_fences is 0, the field is updated
|
||||
* with the actual number of fences. If num_fences is > 0, the system will
|
||||
* use the pointer provided on sync_fence_info to return up to num_fences of
|
||||
* struct sync_fence_info, with detailed fence information.
|
||||
*
|
||||
* This is the new version of the Sync API after the de-stage that happened
|
||||
* on Linux kernel 4.7.
|
||||
*/
|
||||
#define SYNC_IOC_FILE_INFO _IOWR(SYNC_IOC_MAGIC, 4, struct sync_file_info)
|
||||
|
||||
/* timeout in msecs */
|
||||
int sync_wait(int fd, int timeout);
|
||||
int sync_merge(const char *name, int fd1, int fd2);
|
||||
|
|
142
libsync/sync.c
142
libsync/sync.c
|
@ -20,6 +20,8 @@
|
|||
#include <malloc.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
|
@ -27,18 +29,6 @@
|
|||
|
||||
#include <sync/sync.h>
|
||||
|
||||
// The sync code is undergoing a major change. Add enough in to get
|
||||
// everything to compile wih the latest uapi headers.
|
||||
struct sync_merge_data {
|
||||
int32_t fd2;
|
||||
char name[32];
|
||||
int32_t fence;
|
||||
};
|
||||
|
||||
#define SYNC_IOC_MAGIC '>'
|
||||
#define SYNC_IOC_WAIT _IOW(SYNC_IOC_MAGIC, 0, __s32)
|
||||
#define SYNC_IOC_MERGE _IOWR(SYNC_IOC_MAGIC, 1, struct sync_merge_data)
|
||||
#define SYNC_IOC_FENCE_INFO _IOWR(SYNC_IOC_MAGIC, 2, struct sync_fence_info_data)
|
||||
|
||||
struct sw_sync_create_fence_data {
|
||||
__u32 value;
|
||||
|
@ -52,43 +42,133 @@ struct sw_sync_create_fence_data {
|
|||
|
||||
int sync_wait(int fd, int timeout)
|
||||
{
|
||||
__s32 to = timeout;
|
||||
struct pollfd fds;
|
||||
int ret;
|
||||
|
||||
return ioctl(fd, SYNC_IOC_WAIT, &to);
|
||||
if (fd < 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
fds.fd = fd;
|
||||
fds.events = POLLIN;
|
||||
|
||||
do {
|
||||
ret = poll(&fds, 1, timeout);
|
||||
if (ret > 0) {
|
||||
if (fds.revents & (POLLERR | POLLNVAL)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
} else if (ret == 0) {
|
||||
errno = ETIME;
|
||||
return -1;
|
||||
}
|
||||
} while (ret == -1 && (errno == EINTR || errno == EAGAIN));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sync_merge(const char *name, int fd1, int fd2)
|
||||
{
|
||||
struct sync_legacy_merge_data legacy_data;
|
||||
struct sync_merge_data data;
|
||||
int err;
|
||||
int ret;
|
||||
|
||||
data.fd2 = fd2;
|
||||
strlcpy(data.name, name, sizeof(data.name));
|
||||
data.flags = 0;
|
||||
data.pad = 0;
|
||||
|
||||
err = ioctl(fd1, SYNC_IOC_MERGE, &data);
|
||||
if (err < 0)
|
||||
return err;
|
||||
ret = ioctl(fd1, SYNC_IOC_MERGE, &data);
|
||||
if (ret < 0 && errno == ENOTTY) {
|
||||
legacy_data.fd2 = fd2;
|
||||
strlcpy(legacy_data.name, name, sizeof(legacy_data.name));
|
||||
|
||||
ret = ioctl(fd1, SYNC_IOC_LEGACY_MERGE, &legacy_data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return legacy_data.fence;
|
||||
} else if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return data.fence;
|
||||
}
|
||||
|
||||
struct sync_fence_info_data *sync_fence_info(int fd)
|
||||
{
|
||||
struct sync_fence_info_data *info;
|
||||
int err;
|
||||
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;
|
||||
|
||||
info = malloc(4096);
|
||||
if (info == NULL)
|
||||
legacy_info = malloc(4096);
|
||||
if (legacy_info == NULL)
|
||||
return NULL;
|
||||
|
||||
info->len = 4096;
|
||||
err = ioctl(fd, SYNC_IOC_FENCE_INFO, info);
|
||||
if (err < 0) {
|
||||
free(info);
|
||||
legacy_info->len = 4096;
|
||||
err = ioctl(fd, SYNC_IOC_LEGACY_FENCE_INFO, legacy_info);
|
||||
if (err < 0 && errno != ENOTTY) {
|
||||
free(legacy_info);
|
||||
return NULL;
|
||||
} else if (err == 0) {
|
||||
return legacy_info;
|
||||
}
|
||||
|
||||
return info;
|
||||
info = calloc(1, sizeof(*info));
|
||||
if (info == NULL)
|
||||
goto free;
|
||||
|
||||
err = ioctl(fd, SYNC_IOC_FILE_INFO, 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;
|
||||
}
|
||||
}
|
||||
|
||||
legacy_info->len = sizeof(*legacy_info) +
|
||||
num_fences * sizeof(struct sync_fence_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++) {
|
||||
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));
|
||||
strlcpy(legacy_pt_info[i].driver_name, fence_info[i].driver_name,
|
||||
sizeof(legacy_pt_info->driver_name));
|
||||
legacy_pt_info[i].status = fence_info[i].status;
|
||||
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;
|
||||
}
|
||||
|
||||
struct sync_pt_info *sync_pt_info(struct sync_fence_info_data *info,
|
||||
|
@ -113,7 +193,13 @@ void sync_fence_info_free(struct sync_fence_info_data *info)
|
|||
|
||||
int sw_sync_timeline_create(void)
|
||||
{
|
||||
return open("/dev/sw_sync", O_RDWR);
|
||||
int ret;
|
||||
|
||||
ret = open("/sys/kernel/debug/sync/sw_sync", O_RDWR);
|
||||
if (ret < 0)
|
||||
ret = open("/dev/sw_sync", O_RDWR);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sw_sync_timeline_inc(int fd, unsigned count)
|
||||
|
|
|
@ -348,33 +348,6 @@ TEST(FenceTest, MergeSameFence) {
|
|||
ASSERT_EQ(selfMergeFence.getSignaledCount(), 1);
|
||||
}
|
||||
|
||||
TEST(FenceTest, WaitOnDestroyedTimeline) {
|
||||
SyncTimeline timeline;
|
||||
ASSERT_TRUE(timeline.isValid());
|
||||
|
||||
SyncFence fenceSig(timeline, 100);
|
||||
SyncFence fenceKill(timeline, 200);
|
||||
|
||||
// Spawn a thread to wait on a fence when the timeline is killed.
|
||||
thread waitThread{
|
||||
[&]() {
|
||||
ASSERT_EQ(timeline.inc(100), 0);
|
||||
|
||||
ASSERT_EQ(fenceKill.wait(-1), -1);
|
||||
ASSERT_EQ(errno, ENOENT);
|
||||
}
|
||||
};
|
||||
|
||||
// Wait for the thread to spool up.
|
||||
fenceSig.wait();
|
||||
|
||||
// Kill the timeline.
|
||||
timeline.destroy();
|
||||
|
||||
// wait for the thread to clean up.
|
||||
waitThread.join();
|
||||
}
|
||||
|
||||
TEST(FenceTest, PollOnDestroyedTimeline) {
|
||||
SyncTimeline timeline;
|
||||
ASSERT_TRUE(timeline.isValid());
|
||||
|
@ -391,8 +364,7 @@ TEST(FenceTest, PollOnDestroyedTimeline) {
|
|||
struct pollfd fds;
|
||||
fds.fd = fenceKill.getFd();
|
||||
fds.events = POLLIN | POLLERR;
|
||||
ASSERT_EQ(poll(&fds, 1, -1), 1);
|
||||
ASSERT_TRUE(fds.revents & POLLERR);
|
||||
ASSERT_EQ(poll(&fds, 1, 0), 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue