Skip to content

Commit

Permalink
selftests: winesync: Add some tests for wakeup signaling with WINESYN…
Browse files Browse the repository at this point in the history
…C_IOC_WAIT_ANY
  • Loading branch information
Zebediah Figura authored and xanmod committed May 30, 2022
1 parent a55d918 commit f1d89dc
Showing 1 changed file with 154 additions and 0 deletions.
154 changes: 154 additions & 0 deletions tools/testing/selftests/drivers/winesync/winesync.c
Original file line number Diff line number Diff line change
Expand Up @@ -636,4 +636,158 @@ TEST(invalid_objects)
close(fd);
}

struct wake_args
{
int fd;
__u32 obj;
};

struct wait_args
{
int fd;
unsigned long request;
struct winesync_wait_args *args;
int ret;
int err;
};

static void *wait_thread(void *arg)
{
struct wait_args *args = arg;

args->ret = ioctl(args->fd, args->request, args->args);
args->err = errno;
return NULL;
}

static void get_abs_timeout(struct timespec *timeout, clockid_t clock,
unsigned int ms)
{
clock_gettime(clock, timeout);
timeout->tv_nsec += ms * 1000000;
timeout->tv_sec += (timeout->tv_nsec / 1000000000);
timeout->tv_nsec %= 1000000000;
}

static int wait_for_thread(pthread_t thread, unsigned int ms)
{
struct timespec timeout;
get_abs_timeout(&timeout, CLOCK_REALTIME, ms);
return pthread_timedjoin_np(thread, NULL, &timeout);
}

TEST(wake_any)
{
struct winesync_mutex_args mutex_args = {0};
struct winesync_wait_args wait_args = {0};
struct winesync_sem_args sem_args = {0};
struct wait_args thread_args;
__u32 objs[2], count, index;
struct timespec timeout;
pthread_t thread;
int fd, ret;

fd = open("/dev/winesync", O_CLOEXEC | O_RDONLY);
ASSERT_LE(0, fd);

sem_args.count = 0;
sem_args.max = 3;
sem_args.sem = 0xdeadbeef;
ret = ioctl(fd, WINESYNC_IOC_CREATE_SEM, &sem_args);
EXPECT_EQ(0, ret);
EXPECT_NE(0xdeadbeef, sem_args.sem);

mutex_args.owner = 123;
mutex_args.count = 1;
mutex_args.mutex = 0xdeadbeef;
ret = ioctl(fd, WINESYNC_IOC_CREATE_MUTEX, &mutex_args);
EXPECT_EQ(0, ret);
EXPECT_NE(0xdeadbeef, mutex_args.mutex);

objs[0] = sem_args.sem;
objs[1] = mutex_args.mutex;

/* test waking the semaphore */

get_abs_timeout(&timeout, CLOCK_MONOTONIC, 1000);
wait_args.timeout = (uintptr_t)&timeout;
wait_args.objs = (uintptr_t)objs;
wait_args.count = 2;
wait_args.owner = 456;
wait_args.index = 0xdeadbeef;
thread_args.fd = fd;
thread_args.args = &wait_args;
thread_args.request = WINESYNC_IOC_WAIT_ANY;
ret = pthread_create(&thread, NULL, wait_thread, &thread_args);
EXPECT_EQ(0, ret);

ret = wait_for_thread(thread, 100);
EXPECT_EQ(ETIMEDOUT, ret);

sem_args.count = 1;
ret = ioctl(fd, WINESYNC_IOC_PUT_SEM, &sem_args);
EXPECT_EQ(0, ret);
EXPECT_EQ(0, sem_args.count);
check_sem_state(fd, sem_args.sem, 0, 3);

ret = wait_for_thread(thread, 100);
EXPECT_EQ(0, ret);
EXPECT_EQ(0, thread_args.ret);
EXPECT_EQ(0, wait_args.index);

/* test waking the mutex */

/* first grab it again for owner 123 */
ret = wait_any(fd, 1, &mutex_args.mutex, 123, &index);
EXPECT_EQ(0, ret);
EXPECT_EQ(0, index);

get_abs_timeout(&timeout, CLOCK_MONOTONIC, 1000);
wait_args.owner = 456;
ret = pthread_create(&thread, NULL, wait_thread, &thread_args);
EXPECT_EQ(0, ret);

ret = wait_for_thread(thread, 100);
EXPECT_EQ(ETIMEDOUT, ret);

ret = put_mutex(fd, mutex_args.mutex, 123, &count);
EXPECT_EQ(0, ret);
EXPECT_EQ(2, count);

ret = pthread_tryjoin_np(thread, NULL);
EXPECT_EQ(EBUSY, ret);

ret = put_mutex(fd, mutex_args.mutex, 123, &count);
EXPECT_EQ(0, ret);
EXPECT_EQ(1, mutex_args.count);
check_mutex_state(fd, mutex_args.mutex, 1, 456);

ret = wait_for_thread(thread, 100);
EXPECT_EQ(0, ret);
EXPECT_EQ(0, thread_args.ret);
EXPECT_EQ(1, wait_args.index);

/* delete an object while it's being waited on */

get_abs_timeout(&timeout, CLOCK_MONOTONIC, 200);
wait_args.owner = 123;
ret = pthread_create(&thread, NULL, wait_thread, &thread_args);
EXPECT_EQ(0, ret);

ret = wait_for_thread(thread, 100);
EXPECT_EQ(ETIMEDOUT, ret);

ret = ioctl(fd, WINESYNC_IOC_DELETE, &sem_args.sem);
EXPECT_EQ(0, ret);
ret = ioctl(fd, WINESYNC_IOC_DELETE, &mutex_args.mutex);
EXPECT_EQ(0, ret);

ret = wait_for_thread(thread, 200);
EXPECT_EQ(0, ret);
EXPECT_EQ(-1, thread_args.ret);
EXPECT_EQ(ETIMEDOUT, thread_args.err);

close(fd);
}

TEST_HARNESS_MAIN

0 comments on commit f1d89dc

Please sign in to comment.