summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Makefile.sources2
-rw-r--r--lib/igt_gt.c109
-rw-r--r--lib/igt_gt.h35
-rw-r--r--lib/ioctl_wrappers.c33
-rw-r--r--lib/ioctl_wrappers.h12
-rw-r--r--tests/gem_concurrent_blit.c245
6 files changed, 371 insertions, 65 deletions
diff --git a/lib/Makefile.sources b/lib/Makefile.sources
index 34a3d31c..76f353aa 100644
--- a/lib/Makefile.sources
+++ b/lib/Makefile.sources
@@ -10,6 +10,8 @@ libintel_tools_la_SOURCES = \
igt_debugfs.h \
igt_aux.c \
igt_aux.h \
+ igt_gt.c \
+ igt_gt.h \
instdone.c \
instdone.h \
intel_batchbuffer.c \
diff --git a/lib/igt_gt.c b/lib/igt_gt.c
new file mode 100644
index 00000000..526cbee0
--- /dev/null
+++ b/lib/igt_gt.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#include <string.h>
+#include <errno.h>
+
+#include "igt_core.h"
+#include "igt_gt.h"
+#include "igt_debugfs.h"
+#include "ioctl_wrappers.h"
+#include "intel_reg.h"
+
+int igt_can_hang_ring(int fd, int gen, int ring)
+{
+ if (!gem_context_has_param(fd, LOCAL_CONTEXT_PARAM_BAN_PERIOD))
+ return 0;
+
+ if (gen < 5) /* safe resets */
+ return 0;
+
+ return 1;
+}
+
+struct igt_hang_ring igt_hang_ring(int fd, int gen, int ring)
+{
+ struct drm_i915_gem_relocation_entry reloc;
+ struct drm_i915_gem_execbuffer2 execbuf;
+ struct drm_i915_gem_exec_object2 exec;
+ struct local_i915_gem_context_param param;
+ uint32_t b[8];
+ unsigned ban;
+ unsigned len;
+
+ param.context = 0;
+ param.size = 0;
+ param.param = LOCAL_CONTEXT_PARAM_BAN_PERIOD;
+ param.value = 0;
+ gem_context_get_param(fd, &param);
+ ban = param.value;
+
+ param.value = 0;
+ igt_require(gem_context_set_param(fd, &param) == 0);
+
+ memset(&reloc, 0, sizeof(reloc));
+ memset(&exec, 0, sizeof(exec));
+ memset(&execbuf, 0, sizeof(execbuf));
+
+ exec.handle = gem_create(fd, 4096);
+ exec.relocation_count = 1;
+ exec.relocs_ptr = (uintptr_t)&reloc;
+
+ len = 2;
+ if (gen >= 8)
+ len++;
+ b[0] = MI_BATCH_BUFFER_START | (len - 2);
+ b[len] = MI_BATCH_BUFFER_END;
+ b[len+1] = MI_NOOP;
+ gem_write(fd, exec.handle, 0, b, sizeof(b));
+
+ reloc.offset = 4;
+ reloc.target_handle = exec.handle;
+ reloc.read_domains = I915_GEM_DOMAIN_COMMAND;
+
+ execbuf.buffers_ptr = (uintptr_t)&exec;
+ execbuf.buffer_count = 1;
+ execbuf.batch_len = sizeof(b);
+ execbuf.flags = ring;
+ gem_execbuf(fd, &execbuf);
+
+ return (struct igt_hang_ring){ exec.handle, ban };
+}
+
+void igt_post_hang_ring(int fd, struct igt_hang_ring arg)
+{
+ struct local_i915_gem_context_param param;
+
+ if (arg.handle == 0)
+ return;
+
+ gem_set_domain(fd, arg.handle,
+ I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
+ gem_close(fd, arg.handle);
+
+ param.context = 0;
+ param.size = 0;
+ param.param = LOCAL_CONTEXT_PARAM_BAN_PERIOD;
+ param.value = arg.ban;
+ gem_context_set_param(fd, &param);
+}
diff --git a/lib/igt_gt.h b/lib/igt_gt.h
new file mode 100644
index 00000000..19bbcef2
--- /dev/null
+++ b/lib/igt_gt.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#ifndef IGT_GT_H
+#define IGT_GT_H
+
+int igt_can_hang_ring(int fd, int gen, int ring);
+
+struct igt_hang_ring {
+ unsigned handle;
+ unsigned ban;
+} igt_hang_ring(int fd, int gen, int ring);
+void igt_post_hang_ring(int fd, struct igt_hang_ring data);
+
+#endif /* IGT_GT_H */
diff --git a/lib/ioctl_wrappers.c b/lib/ioctl_wrappers.c
index dd48d0e6..5bca4559 100644
--- a/lib/ioctl_wrappers.c
+++ b/lib/ioctl_wrappers.c
@@ -1042,3 +1042,36 @@ off_t prime_get_size(int dma_buf_fd)
return ret;
}
+int gem_context_get_param(int fd, struct local_i915_gem_context_param *p)
+{
+#define LOCAL_I915_GEM_CONTEXT_GETPARAM 0x34
+#define LOCAL_IOCTL_I915_GEM_CONTEXT_GETPARAM DRM_IOWR (DRM_COMMAND_BASE + LOCAL_I915_GEM_CONTEXT_GETPARAM, struct local_i915_gem_context_param)
+ if (drmIoctl(fd, LOCAL_IOCTL_I915_GEM_CONTEXT_GETPARAM, p))
+ return -1;
+
+ errno = 0;
+ return 0;
+}
+
+int gem_context_set_param(int fd, struct local_i915_gem_context_param *p)
+{
+#define LOCAL_I915_GEM_CONTEXT_SETPARAM 0x35
+#define LOCAL_IOCTL_I915_GEM_CONTEXT_SETPARAM DRM_IOWR (DRM_COMMAND_BASE + LOCAL_I915_GEM_CONTEXT_SETPARAM, struct local_i915_gem_context_param)
+ if (drmIoctl(fd, LOCAL_IOCTL_I915_GEM_CONTEXT_SETPARAM, p))
+ return -1;
+
+ errno = 0;
+ return 0;
+}
+
+int gem_context_has_param(int fd, uint64_t param)
+{
+ struct local_i915_gem_context_param p;
+
+ p.context = 0;
+ p.param = param;
+ p.value = 0;
+ p.size = 0;
+
+ return gem_context_get_param(fd, &p) == 0;
+}
diff --git a/lib/ioctl_wrappers.h b/lib/ioctl_wrappers.h
index 9e7edad5..2aa41987 100644
--- a/lib/ioctl_wrappers.h
+++ b/lib/ioctl_wrappers.h
@@ -104,4 +104,16 @@ int prime_handle_to_fd(int fd, uint32_t handle);
uint32_t prime_fd_to_handle(int fd, int dma_buf_fd);
off_t prime_get_size(int dma_buf_fd);
+struct local_i915_gem_context_param {
+ uint32_t context;
+ uint32_t size;
+ uint64_t param;
+#define LOCAL_CONTEXT_PARAM_BAN_PERIOD 0x1
+ uint64_t value;
+};
+
+int gem_context_has_param(int fd, uint64_t param);
+int gem_context_get_param(int fd, struct local_i915_gem_context_param *p);
+int gem_context_set_param(int fd, struct local_i915_gem_context_param *p);
+
#endif /* IOCTL_WRAPPERS_H */
diff --git a/tests/gem_concurrent_blit.c b/tests/gem_concurrent_blit.c
index 9d157b68..48ee48a6 100644
--- a/tests/gem_concurrent_blit.c
+++ b/tests/gem_concurrent_blit.c
@@ -49,11 +49,13 @@
#include "ioctl_wrappers.h"
#include "drmtest.h"
+#include "igt_aux.h"
+#include "igt_core.h"
+#include "igt_gt.h"
#include "intel_bufmgr.h"
#include "intel_batchbuffer.h"
#include "intel_io.h"
#include "intel_chipset.h"
-#include "igt_aux.h"
IGT_TEST_DESCRIPTION("Test of pread/pwrite behavior when writing to active"
" buffers.");
@@ -365,6 +367,7 @@ const int width = 512, height = 512;
igt_render_copyfunc_t rendercopy;
typedef void (*do_copy)(drm_intel_bo *dst, drm_intel_bo *src);
+typedef struct igt_hang_ring (*do_hang)(void);
static void render_copy_bo(drm_intel_bo *dst, drm_intel_bo *src)
{
@@ -454,11 +457,33 @@ static void wc_copy_bo(drm_intel_bo *dst, drm_intel_bo *src)
munmap(s, size);
}
+static struct igt_hang_ring no_hang(void)
+{
+ return (struct igt_hang_ring){0, 0};
+}
+
+static struct igt_hang_ring bcs_hang(void)
+{
+ return igt_hang_ring(fd, gen, I915_EXEC_BLT);
+}
+
+static struct igt_hang_ring rcs_hang(void)
+{
+ return igt_hang_ring(fd, gen, I915_EXEC_RENDER);
+}
+
+static void hang_require(void)
+{
+ igt_require(igt_can_hang_ring(fd, gen, -1));
+}
+
static void do_overwrite_source(const struct access_mode *mode,
drm_intel_bo **src, drm_intel_bo **dst,
drm_intel_bo *dummy,
- do_copy do_copy_func)
+ do_copy do_copy_func,
+ do_hang do_hang_func)
{
+ struct igt_hang_ring hang;
int i;
gem_quiescent_gpu(fd);
@@ -468,17 +493,63 @@ static void do_overwrite_source(const struct access_mode *mode,
}
for (i = 0; i < num_buffers; i++)
do_copy_func(dst[i], src[i]);
+ hang = do_hang_func();
for (i = num_buffers; i--; )
mode->set_bo(src[i], 0xdeadbeef, width, height);
for (i = 0; i < num_buffers; i++)
mode->cmp_bo(dst[i], i, width, height, dummy);
+ igt_post_hang_ring(fd, hang);
+}
+
+static void do_overwrite_source__rev(const struct access_mode *mode,
+ drm_intel_bo **src, drm_intel_bo **dst,
+ drm_intel_bo *dummy,
+ do_copy do_copy_func,
+ do_hang do_hang_func)
+{
+ struct igt_hang_ring hang;
+ int i;
+
+ gem_quiescent_gpu(fd);
+ for (i = 0; i < num_buffers; i++) {
+ mode->set_bo(src[i], i, width, height);
+ mode->set_bo(dst[i], ~i, width, height);
+ }
+ for (i = 0; i < num_buffers; i++)
+ do_copy_func(dst[i], src[i]);
+ hang = do_hang_func();
+ for (i = 0; i < num_buffers; i++)
+ mode->set_bo(src[i], 0xdeadbeef, width, height);
+ for (i = num_buffers; i--; )
+ mode->cmp_bo(dst[i], i, width, height, dummy);
+ igt_post_hang_ring(fd, hang);
+}
+
+static void do_overwrite_source__one(const struct access_mode *mode,
+ drm_intel_bo **src, drm_intel_bo **dst,
+ drm_intel_bo *dummy,
+ do_copy do_copy_func,
+ do_hang do_hang_func)
+{
+ struct igt_hang_ring hang;
+
+ gem_quiescent_gpu(fd);
+ mode->set_bo(src[0], 0, width, height);
+ mode->set_bo(dst[0], ~0, width, height);
+ do_copy_func(dst[0], src[0]);
+ hang = do_hang_func();
+ mode->set_bo(src[0], 0xdeadbeef, width, height);
+ mode->cmp_bo(dst[0], 0, width, height, dummy);
+ igt_post_hang_ring(fd, hang);
}
static void do_early_read(const struct access_mode *mode,
drm_intel_bo **src, drm_intel_bo **dst,
drm_intel_bo *dummy,
- do_copy do_copy_func)
+ do_copy do_copy_func,
+ do_hang do_hang_func)
{
+ struct igt_hang_ring hang;
int i;
gem_quiescent_gpu(fd);
@@ -486,15 +557,19 @@ static void do_early_read(const struct access_mode *mode,
mode->set_bo(src[i], 0xdeadbeef, width, height);
for (i = 0; i < num_buffers; i++)
do_copy_func(dst[i], src[i]);
+ hang = do_hang_func();
for (i = num_buffers; i--; )
mode->cmp_bo(dst[i], 0xdeadbeef, width, height, dummy);
+ igt_post_hang_ring(fd, hang);
}
static void do_gpu_read_after_write(const struct access_mode *mode,
drm_intel_bo **src, drm_intel_bo **dst,
drm_intel_bo *dummy,
- do_copy do_copy_func)
+ do_copy do_copy_func,
+ do_hang do_hang_func)
{
+ struct igt_hang_ring hang;
int i;
gem_quiescent_gpu(fd);
@@ -504,47 +579,54 @@ static void do_gpu_read_after_write(const struct access_mode *mode,
do_copy_func(dst[i], src[i]);
for (i = num_buffers; i--; )
do_copy_func(dummy, dst[i]);
+ hang = do_hang_func();
for (i = num_buffers; i--; )
mode->cmp_bo(dst[i], 0xabcdabcd, width, height, dummy);
+ igt_post_hang_ring(fd, hang);
}
typedef void (*do_test)(const struct access_mode *mode,
drm_intel_bo **src, drm_intel_bo **dst,
drm_intel_bo *dummy,
- do_copy do_copy_func);
+ do_copy do_copy_func,
+ do_hang do_hang_func);
typedef void (*run_wrap)(const struct access_mode *mode,
drm_intel_bo **src, drm_intel_bo **dst,
drm_intel_bo *dummy,
do_test do_test_func,
- do_copy do_copy_func);
+ do_copy do_copy_func,
+ do_hang do_hang_func);
static void run_single(const struct access_mode *mode,
drm_intel_bo **src, drm_intel_bo **dst,
drm_intel_bo *dummy,
do_test do_test_func,
- do_copy do_copy_func)
+ do_copy do_copy_func,
+ do_hang do_hang_func)
{
- do_test_func(mode, src, dst, dummy, do_copy_func);
+ do_test_func(mode, src, dst, dummy, do_copy_func, do_hang_func);
}
static void run_interruptible(const struct access_mode *mode,
drm_intel_bo **src, drm_intel_bo **dst,
drm_intel_bo *dummy,
do_test do_test_func,
- do_copy do_copy_func)
+ do_copy do_copy_func,
+ do_hang do_hang_func)
{
int loop;
for (loop = 0; loop < 10; loop++)
- do_test_func(mode, src, dst, dummy, do_copy_func);
+ do_test_func(mode, src, dst, dummy, do_copy_func, do_hang_func);
}
static void run_forked(const struct access_mode *mode,
drm_intel_bo **src, drm_intel_bo **dst,
drm_intel_bo *dummy,
do_test do_test_func,
- do_copy do_copy_func)
+ do_copy do_copy_func,
+ do_hang do_hang_func)
{
const int old_num_buffers = num_buffers;
@@ -555,6 +637,7 @@ static void run_forked(const struct access_mode *mode,
drm_intel_bufmgr *bufmgr;
/* recreate process local variables */
+ fd = drm_open_any();
bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
drm_intel_bufmgr_gem_enable_reuse(bufmgr);
@@ -567,18 +650,14 @@ static void run_forked(const struct access_mode *mode,
dummy = mode->create_bo(bufmgr, width, height);
for (int loop = 0; loop < 10; loop++)
- do_test_func(mode, src, dst, dummy, do_copy_func);
+ do_test_func(mode, src, dst, dummy,
+ do_copy_func, do_hang_func);
- /* as we borrow the fd, we need to reap our bo */
for (int i = 0; i < num_buffers; i++) {
mode->release_bo(src[i]);
mode->release_bo(dst[i]);
}
mode->release_bo(dummy);
-
- intel_batchbuffer_free(batch);
-
- drm_intel_bufmgr_destroy(bufmgr);
}
igt_waitchildren();
@@ -629,10 +708,13 @@ static void rcs_require(void)
igt_require(rendercopy);
}
+static void no_require(void)
+{
+}
+
static void
run_basic_modes(const struct access_mode *mode,
- drm_intel_bo **src, drm_intel_bo **dst,
- drm_intel_bo *dummy, const char *suffix,
+ const char *suffix,
run_wrap run_wrap_func)
{
const struct {
@@ -647,27 +729,85 @@ run_basic_modes(const struct access_mode *mode,
{ "rcs", render_copy_bo, rcs_require },
{ NULL, NULL }
}, *p;
+ const struct {
+ const char *suffix;
+ do_hang hang;
+ void (*require)(void);
+ } hangs[] = {
+ { "", no_hang, no_require },
+ { "-hang(bcs)", bcs_hang, hang_require },
+ { "-hang(rcs)", rcs_hang, hang_require },
+ { NULL, NULL },
+ }, *h;
+ drm_intel_bo *src[MAX_NUM_BUFFERS], *dst[MAX_NUM_BUFFERS], *dummy = NULL;
+ drm_intel_bufmgr *bufmgr;
- for (p = pipelines; p->prefix; p++) {
- /* try to overwrite the source values */
- igt_subtest_f("%s-%s-overwrite-source%s", mode->name, p->prefix, suffix) {
- p->require();
- run_wrap_func(mode, src, dst, dummy,
- do_overwrite_source, p->copy);
- }
- /* try to read the results before the copy completes */
- igt_subtest_f("%s-%s-early-read%s", mode->name, p->prefix, suffix) {
- p->require();
- run_wrap_func(mode, src, dst, dummy,
- do_early_read, p->copy);
- }
+ for (h = hangs; h->suffix; h++) {
+ for (p = pipelines; p->prefix; p++) {
+ igt_fixture {
+ bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
+ drm_intel_bufmgr_gem_enable_reuse(bufmgr);
+ batch = intel_batchbuffer_alloc(bufmgr, devid);
- /* and finally try to trick the kernel into loosing the pending write */
- igt_subtest_f("%s-%s-gpu-read-after-write%s", mode->name, p->prefix, suffix) {
- p->require();
- run_wrap_func(mode, src, dst, dummy,
- do_gpu_read_after_write, p->copy);
+ for (int i = 0; i < num_buffers; i++) {
+ src[i] = mode->create_bo(bufmgr, width, height);
+ dst[i] = mode->create_bo(bufmgr, width, height);
+ }
+ dummy = mode->create_bo(bufmgr, width, height);
+ }
+
+ /* try to overwrite the source values */
+ igt_subtest_f("%s-%s-overwrite-source-one%s%s", mode->name, p->prefix, suffix, h->suffix) {
+ h->require();
+ p->require();
+ run_wrap_func(mode, src, dst, dummy,
+ do_overwrite_source__one,
+ p->copy, h->hang);
+ }
+
+ igt_subtest_f("%s-%s-overwrite-source%s%s", mode->name, p->prefix, suffix, h->suffix) {
+ h->require();
+ p->require();
+ run_wrap_func(mode, src, dst, dummy,
+ do_overwrite_source,
+ p->copy, h->hang);
+ }
+ igt_subtest_f("%s-%s-overwrite-source-rev%s%s", mode->name, p->prefix, suffix, h->suffix) {
+ h->require();
+ p->require();
+ run_wrap_func(mode, src, dst, dummy,
+ do_overwrite_source__rev,
+ p->copy, h->hang);
+ }
+
+ /* try to read the results before the copy completes */
+ igt_subtest_f("%s-%s-early-read%s%s", mode->name, p->prefix, suffix, h->suffix) {
+ h->require();
+ p->require();
+ run_wrap_func(mode, src, dst, dummy,
+ do_early_read,
+ p->copy, h->hang);
+ }
+
+ /* and finally try to trick the kernel into loosing the pending write */
+ igt_subtest_f("%s-%s-gpu-read-after-write%s%s", mode->name, p->prefix, suffix, h->suffix) {
+ h->require();
+ p->require();
+ run_wrap_func(mode, src, dst, dummy,
+ do_gpu_read_after_write,
+ p->copy, h->hang);
+ }
+
+ igt_fixture {
+ for (int i = 0; i < num_buffers; i++) {
+ mode->release_bo(src[i]);
+ mode->release_bo(dst[i]);
+ }
+ mode->release_bo(dummy);
+ intel_batchbuffer_free(batch);
+ drm_intel_bufmgr_destroy(bufmgr);
+ }
}
}
}
@@ -675,39 +815,14 @@ run_basic_modes(const struct access_mode *mode,
static void
run_modes(const struct access_mode *mode)
{
- drm_intel_bo *src[MAX_NUM_BUFFERS], *dst[MAX_NUM_BUFFERS], *dummy = NULL;
- drm_intel_bufmgr *bufmgr;
-
- igt_fixture {
- bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
- drm_intel_bufmgr_gem_enable_reuse(bufmgr);
- batch = intel_batchbuffer_alloc(bufmgr, devid);
-
- for (int i = 0; i < num_buffers; i++) {
- src[i] = mode->create_bo(bufmgr, width, height);
- dst[i] = mode->create_bo(bufmgr, width, height);
- }
- dummy = mode->create_bo(bufmgr, width, height);
- }
-
- run_basic_modes(mode, src, dst, dummy, "", run_single);
+ run_basic_modes(mode, "", run_single);
igt_fork_signal_helper();
- run_basic_modes(mode, src, dst, dummy, "-interruptible", run_interruptible);
+ run_basic_modes(mode, "-interruptible", run_interruptible);
igt_stop_signal_helper();
- igt_fixture {
- for (int i = 0; i < num_buffers; i++) {
- mode->release_bo(src[i]);
- mode->release_bo(dst[i]);
- }
- mode->release_bo(dummy);
- intel_batchbuffer_free(batch);
- drm_intel_bufmgr_destroy(bufmgr);
- }
-
igt_fork_signal_helper();
- run_basic_modes(mode, src, dst, dummy, "-forked", run_forked);
+ run_basic_modes(mode, "-forked", run_forked);
igt_stop_signal_helper();
}