selftests: ntsync: Add some tests for mutex state.

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

Signed-off-by: Elizabeth Figura <zfigura@codeweavers.com>
Link: https://lore.kernel.org/r/20241213193511.457338-18-zfigura@codeweavers.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Elizabeth Figura
2024-12-13 13:34:58 -06:00
committed by Greg Kroah-Hartman
parent 7f853a252c
commit ae071aef14

View File

@@ -40,6 +40,39 @@ static int release_sem(int sem, __u32 *count)
return ioctl(sem, NTSYNC_IOC_SEM_RELEASE, 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};
@@ -142,4 +175,158 @@ 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;
mutex = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args);
EXPECT_EQ(-1, mutex);
EXPECT_EQ(EINVAL, errno);
mutex_args.owner = 0;
mutex_args.count = 2;
mutex = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args);
EXPECT_EQ(-1, mutex);
EXPECT_EQ(EINVAL, errno);
mutex_args.owner = 123;
mutex_args.count = 2;
mutex = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args);
EXPECT_LE(0, 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 = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args);
EXPECT_LE(0, 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 = ioctl(fd, NTSYNC_IOC_CREATE_MUTEX, &mutex_args);
EXPECT_LE(0, 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