Test mutex-specific ioctls NTSYNC_IOC_MUTEX_UNLOCK and NTSYNC_IOC_MUTEX_READ,
and waiting on mutexes.

Signed-off-by: Elizabeth Figura <zfig...@codeweavers.com>
---
 .../testing/selftests/drivers/ntsync/ntsync.c | 196 ++++++++++++++++++
 1 file changed, 196 insertions(+)

diff --git a/tools/testing/selftests/drivers/ntsync/ntsync.c 
b/tools/testing/selftests/drivers/ntsync/ntsync.c
index 1e145c6dfded..7cd0f40594fd 100644
--- a/tools/testing/selftests/drivers/ntsync/ntsync.c
+++ b/tools/testing/selftests/drivers/ntsync/ntsync.c
@@ -40,6 +40,39 @@ static int post_sem(int sem, __u32 *count)
        return ioctl(sem, NTSYNC_IOC_SEM_POST, count);
 }
 
+static int read_mutex_state(int mutex, __u32 *count, __u32 *owner)
+{
+       struct ntsync_mutex_args args;
+       int ret;
+
+       memset(&args, 0xcc, sizeof(args));
+       ret = ioctl(mutex, NTSYNC_IOC_MUTEX_READ, &args);
+       *count = args.count;
+       *owner = args.owner;
+       return ret;
+}
+
+#define check_mutex_state(mutex, count, owner) \
+       ({ \
+               __u32 __count, __owner; \
+               int ret = read_mutex_state((mutex), &__count, &__owner); \
+               EXPECT_EQ(0, ret); \
+               EXPECT_EQ((count), __count); \
+               EXPECT_EQ((owner), __owner); \
+       })
+
+static int unlock_mutex(int mutex, __u32 owner, __u32 *count)
+{
+       struct ntsync_mutex_args args;
+       int ret;
+
+       args.owner = owner;
+       args.count = 0xdeadbeef;
+       ret = ioctl(mutex, NTSYNC_IOC_MUTEX_UNLOCK, &args);
+       *count = args.count;
+       return ret;
+}
+
 static int wait_any(int fd, __u32 count, const int *objs, __u32 owner, __u32 
*index)
 {
        struct ntsync_wait_args args = {0};
@@ -146,4 +179,167 @@ TEST(semaphore_state)
        close(fd);
 }
 
+TEST(mutex_state)
+{
+       struct ntsync_mutex_args mutex_args;
+       __u32 owner, count, index;
+       struct timespec timeout;
+       int fd, ret, mutex;
+
+       clock_gettime(CLOCK_MONOTONIC, &timeout);
+
+       fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY);
+       ASSERT_LE(0, fd);
+
+       mutex_args.owner = 123;
+       mutex_args.count = 0;
+       ret = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args);
+       EXPECT_EQ(-1, ret);
+       EXPECT_EQ(EINVAL, errno);
+
+       mutex_args.owner = 0;
+       mutex_args.count = 2;
+       ret = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args);
+       EXPECT_EQ(-1, ret);
+       EXPECT_EQ(EINVAL, errno);
+
+       mutex_args.owner = 123;
+       mutex_args.count = 2;
+       mutex_args.mutex = 0xdeadbeef;
+       ret = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args);
+       EXPECT_EQ(0, ret);
+       EXPECT_NE(0xdeadbeef, mutex_args.mutex);
+       mutex = mutex_args.mutex;
+       check_mutex_state(mutex, 2, 123);
+
+       ret = unlock_mutex(mutex, 0, &count);
+       EXPECT_EQ(-1, ret);
+       EXPECT_EQ(EINVAL, errno);
+
+       ret = unlock_mutex(mutex, 456, &count);
+       EXPECT_EQ(-1, ret);
+       EXPECT_EQ(EPERM, errno);
+       check_mutex_state(mutex, 2, 123);
+
+       ret = unlock_mutex(mutex, 123, &count);
+       EXPECT_EQ(0, ret);
+       EXPECT_EQ(2, count);
+       check_mutex_state(mutex, 1, 123);
+
+       ret = unlock_mutex(mutex, 123, &count);
+       EXPECT_EQ(0, ret);
+       EXPECT_EQ(1, count);
+       check_mutex_state(mutex, 0, 0);
+
+       ret = unlock_mutex(mutex, 123, &count);
+       EXPECT_EQ(-1, ret);
+       EXPECT_EQ(EPERM, errno);
+
+       ret = wait_any(fd, 1, &mutex, 456, &index);
+       EXPECT_EQ(0, ret);
+       EXPECT_EQ(0, index);
+       check_mutex_state(mutex, 1, 456);
+
+       ret = wait_any(fd, 1, &mutex, 456, &index);
+       EXPECT_EQ(0, ret);
+       EXPECT_EQ(0, index);
+       check_mutex_state(mutex, 2, 456);
+
+       ret = unlock_mutex(mutex, 456, &count);
+       EXPECT_EQ(0, ret);
+       EXPECT_EQ(2, count);
+       check_mutex_state(mutex, 1, 456);
+
+       ret = wait_any(fd, 1, &mutex, 123, &index);
+       EXPECT_EQ(-1, ret);
+       EXPECT_EQ(ETIMEDOUT, errno);
+
+       owner = 0;
+       ret = ioctl(mutex, NTSYNC_IOC_MUTEX_KILL, &owner);
+       EXPECT_EQ(-1, ret);
+       EXPECT_EQ(EINVAL, errno);
+
+       owner = 123;
+       ret = ioctl(mutex, NTSYNC_IOC_MUTEX_KILL, &owner);
+       EXPECT_EQ(-1, ret);
+       EXPECT_EQ(EPERM, errno);
+       check_mutex_state(mutex, 1, 456);
+
+       owner = 456;
+       ret = ioctl(mutex, NTSYNC_IOC_MUTEX_KILL, &owner);
+       EXPECT_EQ(0, ret);
+
+       memset(&mutex_args, 0xcc, sizeof(mutex_args));
+       ret = ioctl(mutex, NTSYNC_IOC_MUTEX_READ, &mutex_args);
+       EXPECT_EQ(-1, ret);
+       EXPECT_EQ(EOWNERDEAD, errno);
+       EXPECT_EQ(0, mutex_args.count);
+       EXPECT_EQ(0, mutex_args.owner);
+
+       memset(&mutex_args, 0xcc, sizeof(mutex_args));
+       ret = ioctl(mutex, NTSYNC_IOC_MUTEX_READ, &mutex_args);
+       EXPECT_EQ(-1, ret);
+       EXPECT_EQ(EOWNERDEAD, errno);
+       EXPECT_EQ(0, mutex_args.count);
+       EXPECT_EQ(0, mutex_args.owner);
+
+       ret = wait_any(fd, 1, &mutex, 123, &index);
+       EXPECT_EQ(-1, ret);
+       EXPECT_EQ(EOWNERDEAD, errno);
+       EXPECT_EQ(0, index);
+       check_mutex_state(mutex, 1, 123);
+
+       owner = 123;
+       ret = ioctl(mutex, NTSYNC_IOC_MUTEX_KILL, &owner);
+       EXPECT_EQ(0, ret);
+
+       memset(&mutex_args, 0xcc, sizeof(mutex_args));
+       ret = ioctl(mutex, NTSYNC_IOC_MUTEX_READ, &mutex_args);
+       EXPECT_EQ(-1, ret);
+       EXPECT_EQ(EOWNERDEAD, errno);
+       EXPECT_EQ(0, mutex_args.count);
+       EXPECT_EQ(0, mutex_args.owner);
+
+       ret = wait_any(fd, 1, &mutex, 123, &index);
+       EXPECT_EQ(-1, ret);
+       EXPECT_EQ(EOWNERDEAD, errno);
+       EXPECT_EQ(0, index);
+       check_mutex_state(mutex, 1, 123);
+
+       close(mutex);
+
+       mutex_args.owner = 0;
+       mutex_args.count = 0;
+       mutex_args.mutex = 0xdeadbeef;
+       ret = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args);
+       EXPECT_EQ(0, ret);
+       EXPECT_NE(0xdeadbeef, mutex_args.mutex);
+       mutex = mutex_args.mutex;
+       check_mutex_state(mutex, 0, 0);
+
+       ret = wait_any(fd, 1, &mutex, 123, &index);
+       EXPECT_EQ(0, ret);
+       EXPECT_EQ(0, index);
+       check_mutex_state(mutex, 1, 123);
+
+       close(mutex);
+
+       mutex_args.owner = 123;
+       mutex_args.count = ~0u;
+       mutex_args.mutex = 0xdeadbeef;
+       ret = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args);
+       EXPECT_EQ(0, ret);
+       EXPECT_NE(0xdeadbeef, mutex_args.mutex);
+       mutex = mutex_args.mutex;
+       check_mutex_state(mutex, ~0u, 123);
+
+       ret = wait_any(fd, 1, &mutex, 123, &index);
+       EXPECT_EQ(-1, ret);
+       EXPECT_EQ(ETIMEDOUT, errno);
+
+       close(mutex);
+
+       close(fd);
+}
+
 TEST_HARNESS_MAIN
-- 
2.45.2


Reply via email to