lkml.org 
[lkml]   [2024]   [Feb]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 22/31] selftests: ntsync: Add some tests for wakeup signaling with WINESYNC_IOC_WAIT_ANY.
    Date
    Test contended "wait-for-any" waits, to make sure that scheduling and wakeup
    logic works correctly.

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

    diff --git a/tools/testing/selftests/drivers/ntsync/ntsync.c b/tools/testing/selftests/drivers/ntsync/ntsync.c
    index 6bb3bdc2ef3c..e825e115f11f 100644
    --- a/tools/testing/selftests/drivers/ntsync/ntsync.c
    +++ b/tools/testing/selftests/drivers/ntsync/ntsync.c
    @@ -556,4 +556,154 @@ TEST(test_wait_all)
    close(fd);
    }

    +struct wake_args {
    + int fd;
    + int obj;
    +};
    +
    +struct wait_args {
    + int fd;
    + unsigned long request;
    + struct ntsync_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 __u64 get_abs_timeout(unsigned int ms)
    +{
    + struct timespec timeout;
    + clock_gettime(CLOCK_MONOTONIC, &timeout);
    + return (timeout.tv_sec * 1000000000) + timeout.tv_nsec + (ms * 1000000);
    +}
    +
    +static int wait_for_thread(pthread_t thread, unsigned int ms)
    +{
    + struct timespec timeout;
    +
    + clock_gettime(CLOCK_REALTIME, &timeout);
    + timeout.tv_nsec += ms * 1000000;
    + timeout.tv_sec += (timeout.tv_nsec / 1000000000);
    + timeout.tv_nsec %= 1000000000;
    + return pthread_timedjoin_np(thread, NULL, &timeout);
    +}
    +
    +TEST(wake_any)
    +{
    + struct ntsync_mutex_args mutex_args = {0};
    + struct ntsync_wait_args wait_args = {0};
    + struct ntsync_sem_args sem_args = {0};
    + struct wait_args thread_args;
    + int objs[2], fd, ret;
    + __u32 count, index;
    + pthread_t thread;
    +
    + fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY);
    + ASSERT_LE(0, fd);
    +
    + sem_args.count = 0;
    + sem_args.max = 3;
    + sem_args.sem = 0xdeadbeef;
    + ret = ioctl(fd, NTSYNC_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, NTSYNC_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 */
    +
    + wait_args.timeout = get_abs_timeout(1000);
    + 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 = NTSYNC_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);
    +
    + count = 1;
    + ret = post_sem(sem_args.sem, &count);
    + EXPECT_EQ(0, ret);
    + EXPECT_EQ(0, count);
    + check_sem_state(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);
    +
    + wait_args.timeout = get_abs_timeout(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 = unlock_mutex(mutex_args.mutex, 123, &count);
    + EXPECT_EQ(0, ret);
    + EXPECT_EQ(2, count);
    +
    + ret = pthread_tryjoin_np(thread, NULL);
    + EXPECT_EQ(EBUSY, ret);
    +
    + ret = unlock_mutex(mutex_args.mutex, 123, &count);
    + EXPECT_EQ(0, ret);
    + EXPECT_EQ(1, mutex_args.count);
    + check_mutex_state(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 */
    +
    + wait_args.timeout = get_abs_timeout(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);
    +
    + close(sem_args.sem);
    + close(mutex_args.mutex);
    +
    + 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
    --
    2.43.0

    \
     
     \ /
      Last update: 2024-05-27 15:04    [W:7.624 / U:0.084 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site