[RFC][PATCH 3/3] kselftest: Add drm_syncobj API test tool
John Stultz
jstultz at google.com
Tue Jul 12 04:22:58 UTC 2022
An initial pass at a drm_syncobj API test.
Currently covers trivial use of:
DRM_IOCTL_SYNCOBJ_CREATE
DRM_IOCTL_SYNCOBJ_DESTROY
DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD
DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE
DRM_IOCTL_SYNCOBJ_WAIT
DRM_IOCTL_SYNCOBJ_RESET
DRM_IOCTL_SYNCOBJ_SIGNAL
DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT
DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL
And demonstrates how the userspace API can be used, along with
some fairly simple bad parameter checking.
The patch includes a few helpers taken from libdrm, as at least
on the VM I was testing with, I didn't have a new enough libdrm
to support the *_TIMELINE_* ioctls. Ideally the ioctl-helper bits
can be dropped at a later time.
Feedback would be appreciated!
Cc: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
Cc: Maxime Ripard <mripard at kernel.org>
Cc: Thomas Zimmermann <tzimmermann at suse.de>
Cc: Jason Ekstrand <jason at jlekstrand.net>
Cc: Christian König <christian.koenig at amd.com>
Cc: Lionel Landwerlin <lionel.g.landwerlin at intel.com>
Cc: Chunming Zhou <david1.zhou at amd.com>
Cc: David Airlie <airlied at linux.ie>
Cc: Daniel Vetter <daniel at ffwll.ch>
Cc: Shuah Khan <shuah at kernel.org>
Cc: dri-devel at lists.freedesktop.org
Signed-off-by: John Stultz <jstultz at google.com>
---
.../drivers/gpu/drm_syncobj/Makefile | 11 +
.../drivers/gpu/drm_syncobj/ioctl-helper.c | 85 ++++
.../drivers/gpu/drm_syncobj/ioctl-helper.h | 74 ++++
.../drivers/gpu/drm_syncobj/syncobj-test.c | 410 ++++++++++++++++++
4 files changed, 580 insertions(+)
create mode 100644 tools/testing/selftests/drivers/gpu/drm_syncobj/Makefile
create mode 100644 tools/testing/selftests/drivers/gpu/drm_syncobj/ioctl-helper.c
create mode 100644 tools/testing/selftests/drivers/gpu/drm_syncobj/ioctl-helper.h
create mode 100644 tools/testing/selftests/drivers/gpu/drm_syncobj/syncobj-test.c
diff --git a/tools/testing/selftests/drivers/gpu/drm_syncobj/Makefile b/tools/testing/selftests/drivers/gpu/drm_syncobj/Makefile
new file mode 100644
index 000000000000..6576d9b2006c
--- /dev/null
+++ b/tools/testing/selftests/drivers/gpu/drm_syncobj/Makefile
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0
+CFLAGS += -I/usr/include/libdrm/
+LDFLAGS += -pthread -ldrm
+
+TEST_GEN_FILES= syncobj-test
+
+include ../../../lib.mk
+
+$(OUTPUT)/syncobj-test: syncobj-test.c ioctl-helper.c
+EXTRA_CLEAN = $(OUTPUT)/ioctl-helper.o
+
diff --git a/tools/testing/selftests/drivers/gpu/drm_syncobj/ioctl-helper.c b/tools/testing/selftests/drivers/gpu/drm_syncobj/ioctl-helper.c
new file mode 100644
index 000000000000..e5c59c9bed36
--- /dev/null
+++ b/tools/testing/selftests/drivers/gpu/drm_syncobj/ioctl-helper.c
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: MIT
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <errno.h>
+#include <libdrm/drm.h>
+#include <xf86drm.h>
+#include "ioctl-helper.h"
+
+#ifndef DRM_CAP_SYNCOBJ_TIMELINE
+/*
+ * The following is nabbed from libdrm's xf86drm.c as the
+ * installed libdrm doesn't yet include these definitions
+ *
+ *
+ * \author Rickard E. (Rik) Faith <faith at valinux.com>
+ * \author Kevin E. Martin <martin at valinux.com>
+ */
+/*
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+int drmSyncobjTimelineSignal(int fd, const uint32_t *handles,
+ uint64_t *points, uint32_t handle_count)
+{
+ struct drm_syncobj_timeline_array args;
+ int ret;
+
+ memset(&args, 0, sizeof(args));
+ args.handles = (uintptr_t)handles;
+ args.points = (uintptr_t)points;
+ args.count_handles = handle_count;
+
+ ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL, &args);
+ return ret;
+}
+
+int drmSyncobjTimelineWait(int fd, uint32_t *handles, uint64_t *points,
+ unsigned int num_handles,
+ int64_t timeout_nsec, unsigned int flags,
+ uint32_t *first_signaled)
+{
+ struct drm_syncobj_timeline_wait args;
+ int ret;
+
+ memset(&args, 0, sizeof(args));
+ args.handles = (uintptr_t)handles;
+ args.points = (uintptr_t)points;
+ args.timeout_nsec = timeout_nsec;
+ args.count_handles = num_handles;
+ args.flags = flags;
+
+ ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT, &args);
+ if (ret < 0)
+ return -errno;
+
+ if (first_signaled)
+ *first_signaled = args.first_signaled;
+ return ret;
+}
+
+#endif
diff --git a/tools/testing/selftests/drivers/gpu/drm_syncobj/ioctl-helper.h b/tools/testing/selftests/drivers/gpu/drm_syncobj/ioctl-helper.h
new file mode 100644
index 000000000000..b0c1025034b5
--- /dev/null
+++ b/tools/testing/selftests/drivers/gpu/drm_syncobj/ioctl-helper.h
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: MIT */
+#ifndef __IOCTL_HELPER_H__
+#define __IOCTL_HELPER_H__
+
+/* Bits pulled from libdrm's include/drm/drm.h */
+#ifndef DRM_CAP_SYNCOBJ_TIMELINE
+/*
+ * Header for the Direct Rendering Manager
+ *
+ * Author: Rickard E. (Rik) Faith <faith at valinux.com>
+ *
+ * Acknowledgments:
+ * Dec 1999, Richard Henderson <rth at twiddle.net>, move to generic cmpxchg.
+ */
+
+/*
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+struct drm_syncobj_timeline_wait {
+ __u64 handles;
+ /* wait on specific timeline point for every handles*/
+ __u64 points;
+ /* absolute timeout */
+ __s64 timeout_nsec;
+ __u32 count_handles;
+ __u32 flags;
+ __u32 first_signaled; /* only valid when not waiting all */
+ __u32 pad;
+};
+
+
+#define DRM_SYNCOBJ_QUERY_FLAGS_LAST_SUBMITTED (1 << 0)
+struct drm_syncobj_timeline_array {
+ __u64 handles;
+ __u64 points;
+ __u32 count_handles;
+ __u32 flags;
+};
+
+#define DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT DRM_IOWR(0xCA, struct drm_syncobj_timeline_wait)
+#define DRM_IOCTL_SYNCOBJ_QUERY DRM_IOWR(0xCB, struct drm_syncobj_timeline_array)
+#define DRM_IOCTL_SYNCOBJ_TRANSFER DRM_IOWR(0xCC, struct drm_syncobj_transfer)
+#define DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL DRM_IOWR(0xCD, struct drm_syncobj_timeline_array)
+
+int drmSyncobjTimelineSignal(int fd, const uint32_t *handles,
+ uint64_t *points, uint32_t handle_count);
+int drmSyncobjTimelineWait(int fd, uint32_t *handles, uint64_t *points,
+ unsigned int num_handles,
+ int64_t timeout_nsec, unsigned int flags,
+ uint32_t *first_signaled);
+#endif
+#endif /*__IOCTL_HELPER_H__*/
+
diff --git a/tools/testing/selftests/drivers/gpu/drm_syncobj/syncobj-test.c b/tools/testing/selftests/drivers/gpu/drm_syncobj/syncobj-test.c
new file mode 100644
index 000000000000..21474b0d3b9e
--- /dev/null
+++ b/tools/testing/selftests/drivers/gpu/drm_syncobj/syncobj-test.c
@@ -0,0 +1,410 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * This test exercises basic syncobj ioctl interfaces from
+ * userland via the libdrm helpers.
+ *
+ * Copyright (C) 2022, Google LLC.
+ *
+ * Currently covers trivial use of:
+ * DRM_IOCTL_SYNCOBJ_CREATE
+ * DRM_IOCTL_SYNCOBJ_DESTROY
+ * DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD
+ * DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE
+ * DRM_IOCTL_SYNCOBJ_WAIT
+ * DRM_IOCTL_SYNCOBJ_RESET
+ * DRM_IOCTL_SYNCOBJ_SIGNAL
+ * DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT
+ * DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL
+ *
+ * TODO: Need coverage for the following ioctls:
+ * DRM_IOCTL_SYNCOBJ_QUERY
+ * DRM_IOCTL_SYNCOBJ_TRANSFER
+ * As well as more complicated use of interface (like
+ * signal/wait with multiple handles, etc), and sync_file
+ * import/export.
+ */
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <poll.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <pthread.h>
+#include <linux/dma-buf.h>
+#include <libdrm/drm.h>
+#include <xf86drm.h>
+
+#include "ioctl-helper.h"
+
+
+#define NSEC_PER_SEC 1000000000ULL
+static uint64_t get_abs_timeout(uint64_t rel_nsec)
+{
+ struct timespec ts;
+ uint64_t ns;
+
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ ns = ts.tv_sec * NSEC_PER_SEC + ts.tv_nsec;
+ ns += rel_nsec;
+ return ns;
+}
+
+struct test_arg {
+ int dev_fd;
+ uint32_t handle;
+ int handle_fd;
+};
+#define TEST_TIMES 5
+
+void *syncobj_signal_reset(void *arg)
+{
+ struct test_arg *d = (struct test_arg *)arg;
+ int ret;
+ int i;
+
+ for (i = 0; i < TEST_TIMES; i++) {
+ sleep(3);
+ printf("%s: sending signal!\n", __func__);
+ ret = drmSyncobjSignal(d->dev_fd, &d->handle, 1);
+ if (ret)
+ printf("Signal failed %i\n", ret);
+ }
+ return NULL;
+}
+
+static int syncobj_wait_reset(struct test_arg *d)
+{
+ uint64_t abs_timeout;
+ int ret;
+ int i;
+
+ for (i = 0; i < TEST_TIMES; i++) {
+ abs_timeout = get_abs_timeout(10*NSEC_PER_SEC);
+ printf("%s calling drmSyncobjWait\n", __func__);
+ ret = drmSyncobjWait(d->dev_fd, &d->handle, 1, abs_timeout,
+ DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT,
+ NULL);
+ if (ret) {
+ printf("Error: syncobjwait failed %i\n", ret);
+ break;
+ }
+ printf("%s: drmSyncobjWait returned!\n", __func__);
+
+ ret = drmSyncobjReset(d->dev_fd, &d->handle, 1);
+ if (ret) {
+ printf("Error: syncobjreset failed\n");
+ break;
+ }
+ }
+ return ret;
+}
+
+void *syncobj_signal_timeline(void *arg)
+{
+ struct test_arg *d = (struct test_arg *)arg;
+ uint64_t point = 0;
+ int ret;
+
+ for (point = 0; point <= (TEST_TIMES-1)*5; point++) {
+ sleep(1);
+ printf("%s: sending signal %lld!\n", __func__, point);
+ ret = drmSyncobjTimelineSignal(d->dev_fd, &d->handle, &point, 1);
+ if (ret)
+ printf("Signal failed %i\n", ret);
+ }
+ return NULL;
+}
+
+
+int syncobj_timeline_wait(struct test_arg *d)
+{
+ uint64_t abs_timeout;
+ uint64_t point;
+ int ret;
+ int i;
+
+ for (i = 0; i < TEST_TIMES; i++) {
+ abs_timeout = get_abs_timeout(10*NSEC_PER_SEC);
+
+ point = i * 5;
+ printf("%s: drmSyncobjTimelineWait waiting on %lld!\n", __func__, point);
+ ret = drmSyncobjTimelineWait(d->dev_fd, &d->handle, &point, 1,
+ abs_timeout,
+ DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT,
+ NULL);
+ if (ret) {
+ printf("Error: syncobjwait failed %i\n", ret);
+ return ret;
+ }
+ printf("%s: drmSyncobjTimelineWait got %lld!\n", __func__, point);
+ }
+ return 0;
+}
+
+
+static int test_thread_signal_wait(int devfd, void *(*signal_fn)(void *),
+ int (*wait_fn)(struct test_arg *))
+{
+ uint32_t handle;
+ struct test_arg d;
+ pthread_t pth;
+ int ret;
+
+ ret = drmSyncobjCreate(devfd, 0, &handle);
+ if (ret) {
+ printf("Error: Couldn't create syncobj\n");
+ return ret;
+ }
+
+ d.dev_fd = devfd;
+ d.handle = handle;
+
+ pthread_create(&pth, 0, signal_fn, &d);
+ ret = wait_fn(&d);
+ pthread_join(pth, NULL);
+ drmSyncobjDestroy(devfd, handle);
+
+ return ret;
+}
+
+static int test_fork_signal_wait(int devfd, void *(*signal_fn)(void *),
+ int (*wait_fn)(struct test_arg *))
+{
+ uint32_t handle;
+ struct test_arg p, c;
+ pid_t id;
+ int ret;
+
+ ret = drmSyncobjCreate(devfd, 0, &handle);
+ if (ret) {
+ printf("Error: Couldn't create syncobj\n");
+ return ret;
+ }
+
+ p.dev_fd = devfd;
+ p.handle = 0;
+ p.handle_fd = 0;
+ c = p;
+ p.handle = handle;
+
+ ret = drmSyncobjHandleToFD(devfd, handle, &c.handle_fd);
+ if (ret) {
+ printf("Error: Couldn't convert handle to fd\n");
+ goto out;
+ }
+
+ id = fork();
+ if (id == 0) {
+ ret = drmSyncobjFDToHandle(c.dev_fd, c.handle_fd, &c.handle);
+ if (ret) {
+ printf("Error: Couldn't convert fd to handle\n");
+ exit(-1);
+ }
+ close(c.handle_fd);
+ signal_fn((void *)&c);
+ exit(0);
+ } else {
+ ret = wait_fn(&p);
+ waitpid(id, 0, 0);
+ }
+
+out:
+ if (c.handle_fd)
+ close(c.handle_fd);
+ drmSyncobjDestroy(devfd, handle);
+
+ return ret;
+}
+
+
+static int test_badparameters(int devfd)
+{
+ uint32_t handle1, handle2;
+ int ret, fail = 0;
+
+ /* create bad fd */
+ ret = drmSyncobjCreate(-1, 0, &handle1);
+ if (!ret || errno != EBADF) {
+ printf("drmSyncobjCreate - bad fd fails! (%i != EBADF)\n", errno);
+ fail = 1;
+ }
+ /* destroy bad fd */
+ ret = drmSyncobjDestroy(-1, handle1);
+ if (!ret || errno != EBADF) {
+ printf("drmSyncobjDestroy - bad fd fails! (%i != EBADF)\n", errno);
+ fail = 1;
+ }
+
+ /* TODO: Bad flags */
+
+ ret = drmSyncobjCreate(devfd, 0, &handle1);
+ if (ret) {
+ printf("drmSyncobjCreate - unexpected failure!\n");
+ fail = 1;
+ }
+
+ /* Destroy zeroed handle */
+ handle2 = 0;
+ ret = drmSyncobjDestroy(devfd, handle2);
+ if (!ret || errno != EINVAL) {
+ printf("drmSyncobjDestroy - zero'ed handle! (%i != EINVAL)\n", errno);
+ fail = 1;
+ }
+ /* Destroy invalid handle */
+ handle2 = -1;
+ ret = drmSyncobjDestroy(devfd, handle2);
+ if (!ret || errno != EINVAL) {
+ printf("drmSyncobjDestroy - invalid handle! (%i != EINVAL)\n", errno);
+ fail = 1;
+ }
+
+ /* invalid timeouts */
+ ret = drmSyncobjWait(devfd, &handle1, 1, 1000,
+ DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT,
+ NULL);
+ if (!ret || errno != ETIME) {
+ printf("drmSyncobjWait - invalid timeout (relative)! (%i != ETIME)\n", errno);
+ fail = 1;
+ }
+
+ ret = drmSyncobjWait(devfd, &handle1, 1, -1,
+ DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT,
+ NULL);
+ if (!ret || errno != ETIME) {
+ printf("drmSyncobjWait - invalid timeout (-1)! (%i != ETIME)\n", errno);
+ fail = 1;
+ }
+
+ ret = drmSyncobjDestroy(devfd, handle1);
+ if (ret) {
+ printf("drmSyncobjDestroy - unexpected failure!\n");
+ fail = 1;
+ }
+
+
+ return fail;
+}
+
+
+#define NAME_LEN 16
+static int check_device(int fd)
+{
+ drm_version_t version = { 0 };
+ char name[NAME_LEN];
+ uint32_t handle;
+ int ret;
+
+ memset(name, 0, NAME_LEN);
+ version.name_len = NAME_LEN;
+ version.name = name;
+
+ ret = ioctl(fd, DRM_IOCTL_VERSION, &version);
+ if (ret)
+ return -1;
+
+ printf("%s name: %s\n", __func__, name);
+
+ ret = drmSyncobjCreate(fd, 0, &handle);
+ if (!ret) {
+ drmSyncobjDestroy(fd, handle);
+ printf("%s selected: %s\n", __func__, name);
+ }
+ return ret;
+}
+
+static int find_device(void)
+{
+ int i, fd;
+ const char *drmstr = "/dev/dri/card";
+
+ fd = -1;
+ for (i = 0; i < 16; i++) {
+ char name[80];
+
+ snprintf(name, 80, "%s%u", drmstr, i);
+
+ fd = open(name, O_RDWR);
+ if (fd < 0)
+ continue;
+
+ if (check_device(fd)) {
+ close(fd);
+ fd = -1;
+ continue;
+ } else {
+ break;
+ }
+ }
+ return fd;
+}
+
+int main(int argc, char **argv)
+{
+ int devfd = find_device();
+ char *testname;
+ int ret;
+
+ if (devfd < 0) {
+ printf("Error: Couldn't find supported drm device\n");
+ return devfd;
+ }
+
+ testname = "Bad parameters test";
+ printf("\n%s\n", testname);
+ printf("===================\n");
+ ret = test_badparameters(devfd);
+ if (ret)
+ printf("%s: FAILED\n", testname);
+ else
+ printf("%s: PASSED\n", testname);
+
+
+ testname = "Threaded reset test";
+ printf("\n%s\n", testname);
+ printf("===================\n");
+ ret = test_thread_signal_wait(devfd, &syncobj_signal_reset, &syncobj_wait_reset);
+ if (ret)
+ printf("%s: FAILED\n", testname);
+ else
+ printf("%s: PASSED\n", testname);
+
+ testname = "Threaded timeline test";
+ printf("\n%s\n", testname);
+ printf("===================\n");
+ ret = test_thread_signal_wait(devfd, &syncobj_signal_timeline, &syncobj_timeline_wait);
+ if (ret)
+ printf("%s: FAILED\n", testname);
+ else
+ printf("%s: PASSED\n", testname);
+
+
+ testname = "Forked reset test";
+ printf("\n%s\n", testname);
+ printf("===================\n");
+ ret = test_fork_signal_wait(devfd, &syncobj_signal_reset, &syncobj_wait_reset);
+ if (ret)
+ printf("\n%s: FAILED\n", testname);
+ else
+ printf("\n%s: PASSED\n", testname);
+
+ testname = "Forked timeline test";
+ printf("\n%s\n", testname);
+ printf("===================\n");
+ ret = test_fork_signal_wait(devfd, &syncobj_signal_timeline, &syncobj_timeline_wait);
+ if (ret)
+ printf("\n%s: FAILED\n", testname);
+ else
+ printf("\n%s: PASSED\n", testname);
+
+
+ close(devfd);
+ return 0;
+}
--
2.37.0.144.g8ac04bfd2-goog
More information about the dri-devel
mailing list