lkml.org 
[lkml]   [2024]   [Feb]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v2 18/31] selftests: ntsync: Add some tests for semaphore state.
    Date
    Wine has tests for its synchronization primitives, but these are more accessible
    to kernel developers, and also allow us to test some edge cases that Wine does
    not care about.

    This patch adds tests for semaphore-specific ioctls NTSYNC_IOC_SEM_POST and
    NTSYNC_IOC_SEM_READ, and waiting on semaphores.

    Signed-off-by: Elizabeth Figura <zfigura@codeweavers.com>
    ---
    tools/testing/selftests/Makefile | 1 +
    .../testing/selftests/drivers/ntsync/Makefile | 8 +
    tools/testing/selftests/drivers/ntsync/config | 1 +
    .../testing/selftests/drivers/ntsync/ntsync.c | 149 ++++++++++++++++++
    4 files changed, 159 insertions(+)
    create mode 100644 tools/testing/selftests/drivers/ntsync/Makefile
    create mode 100644 tools/testing/selftests/drivers/ntsync/config
    create mode 100644 tools/testing/selftests/drivers/ntsync/ntsync.c

    diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
    index 15b6a111c3be..6c714a4e6478 100644
    --- a/tools/testing/selftests/Makefile
    +++ b/tools/testing/selftests/Makefile
    @@ -15,6 +15,7 @@ TARGETS += cpu-hotplug
    TARGETS += damon
    TARGETS += dmabuf-heaps
    TARGETS += drivers/dma-buf
    +TARGETS += drivers/ntsync
    TARGETS += drivers/s390x/uvdevice
    TARGETS += drivers/net/bonding
    TARGETS += drivers/net/team
    diff --git a/tools/testing/selftests/drivers/ntsync/Makefile b/tools/testing/selftests/drivers/ntsync/Makefile
    new file mode 100644
    index 000000000000..a34da5ccacf0
    --- /dev/null
    +++ b/tools/testing/selftests/drivers/ntsync/Makefile
    @@ -0,0 +1,8 @@
    +# SPDX-LICENSE-IDENTIFIER: GPL-2.0-only
    +TEST_GEN_PROGS := ntsync
    +
    +top_srcdir =../../../../..
    +CFLAGS += -I$(top_srcdir)/usr/include
    +LDLIBS += -lpthread
    +
    +include ../../lib.mk
    diff --git a/tools/testing/selftests/drivers/ntsync/config b/tools/testing/selftests/drivers/ntsync/config
    new file mode 100644
    index 000000000000..60539c826d06
    --- /dev/null
    +++ b/tools/testing/selftests/drivers/ntsync/config
    @@ -0,0 +1 @@
    +CONFIG_WINESYNC=y
    diff --git a/tools/testing/selftests/drivers/ntsync/ntsync.c b/tools/testing/selftests/drivers/ntsync/ntsync.c
    new file mode 100644
    index 000000000000..1e145c6dfded
    --- /dev/null
    +++ b/tools/testing/selftests/drivers/ntsync/ntsync.c
    @@ -0,0 +1,149 @@
    +// SPDX-License-Identifier: GPL-2.0-or-later
    +/*
    + * Various unit tests for the "ntsync" synchronization primitive driver.
    + *
    + * Copyright (C) 2021-2022 Elizabeth Figura <zfigura@codeweavers.com>
    + */
    +
    +#define _GNU_SOURCE
    +#include <sys/ioctl.h>
    +#include <sys/stat.h>
    +#include <fcntl.h>
    +#include <time.h>
    +#include <pthread.h>
    +#include <linux/ntsync.h>
    +#include "../../kselftest_harness.h"
    +
    +static int read_sem_state(int sem, __u32 *count, __u32 *max)
    +{
    + struct ntsync_sem_args args;
    + int ret;
    +
    + memset(&args, 0xcc, sizeof(args));
    + ret = ioctl(sem, NTSYNC_IOC_SEM_READ, &args);
    + *count = args.count;
    + *max = args.max;
    + return ret;
    +}
    +
    +#define check_sem_state(sem, count, max) \
    + ({ \
    + __u32 __count, __max; \
    + int ret = read_sem_state((sem), &__count, &__max); \
    + EXPECT_EQ(0, ret); \
    + EXPECT_EQ((count), __count); \
    + EXPECT_EQ((max), __max); \
    + })
    +
    +static int post_sem(int sem, __u32 *count)
    +{
    + return ioctl(sem, NTSYNC_IOC_SEM_POST, count);
    +}
    +
    +static int wait_any(int fd, __u32 count, const int *objs, __u32 owner, __u32 *index)
    +{
    + struct ntsync_wait_args args = {0};
    + struct timespec timeout;
    + int ret;
    +
    + clock_gettime(CLOCK_MONOTONIC, &timeout);
    +
    + args.timeout = timeout.tv_sec * 1000000000 + timeout.tv_nsec;
    + args.count = count;
    + args.objs = (uintptr_t)objs;
    + args.owner = owner;
    + args.index = 0xdeadbeef;
    + ret = ioctl(fd, NTSYNC_IOC_WAIT_ANY, &args);
    + *index = args.index;
    + return ret;
    +}
    +
    +TEST(semaphore_state)
    +{
    + struct ntsync_sem_args sem_args;
    + struct timespec timeout;
    + __u32 count, index;
    + int fd, ret, sem;
    +
    + clock_gettime(CLOCK_MONOTONIC, &timeout);
    +
    + fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY);
    + ASSERT_LE(0, fd);
    +
    + sem_args.count = 3;
    + sem_args.max = 2;
    + sem_args.sem = 0xdeadbeef;
    + ret = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args);
    + EXPECT_EQ(-1, ret);
    + EXPECT_EQ(EINVAL, errno);
    +
    + sem_args.count = 2;
    + sem_args.max = 2;
    + sem_args.sem = 0xdeadbeef;
    + ret = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args);
    + EXPECT_EQ(0, ret);
    + EXPECT_NE(0xdeadbeef, sem_args.sem);
    + sem = sem_args.sem;
    + check_sem_state(sem, 2, 2);
    +
    + count = 0;
    + ret = post_sem(sem, &count);
    + EXPECT_EQ(0, ret);
    + EXPECT_EQ(2, count);
    + check_sem_state(sem, 2, 2);
    +
    + count = 1;
    + ret = post_sem(sem, &count);
    + EXPECT_EQ(-1, ret);
    + EXPECT_EQ(EOVERFLOW, errno);
    + check_sem_state(sem, 2, 2);
    +
    + ret = wait_any(fd, 1, &sem, 123, &index);
    + EXPECT_EQ(0, ret);
    + EXPECT_EQ(0, index);
    + check_sem_state(sem, 1, 2);
    +
    + ret = wait_any(fd, 1, &sem, 123, &index);
    + EXPECT_EQ(0, ret);
    + EXPECT_EQ(0, index);
    + check_sem_state(sem, 0, 2);
    +
    + ret = wait_any(fd, 1, &sem, 123, &index);
    + EXPECT_EQ(-1, ret);
    + EXPECT_EQ(ETIMEDOUT, errno);
    +
    + count = 3;
    + ret = post_sem(sem, &count);
    + EXPECT_EQ(-1, ret);
    + EXPECT_EQ(EOVERFLOW, errno);
    + check_sem_state(sem, 0, 2);
    +
    + count = 2;
    + ret = post_sem(sem, &count);
    + EXPECT_EQ(0, ret);
    + EXPECT_EQ(0, count);
    + check_sem_state(sem, 2, 2);
    +
    + ret = wait_any(fd, 1, &sem, 123, &index);
    + EXPECT_EQ(0, ret);
    + ret = wait_any(fd, 1, &sem, 123, &index);
    + EXPECT_EQ(0, ret);
    +
    + count = 1;
    + ret = post_sem(sem, &count);
    + EXPECT_EQ(0, ret);
    + EXPECT_EQ(0, count);
    + check_sem_state(sem, 1, 2);
    +
    + count = ~0u;
    + ret = post_sem(sem, &count);
    + EXPECT_EQ(-1, ret);
    + EXPECT_EQ(EOVERFLOW, errno);
    + check_sem_state(sem, 1, 2);
    +
    + close(sem);
    +
    + close(fd);
    +}
    +
    +TEST_HARNESS_MAIN
    --
    2.43.0

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