diff mbox series

[v2] starvation.c: New case for sched starvation

Message ID 20230507142209.17815-1-wegao@suse.com
State Accepted
Headers show
Series [v2] starvation.c: New case for sched starvation | expand

Commit Message

Wei Gao May 7, 2023, 2:22 p.m. UTC
Signed-off-by: Wei Gao <wegao@suse.com>

Add scheduller thread starvation test case base following link:
https://lwn.net/ml/linux-kernel/9fd2c37a05713c206dcbd5866f67ce779f315e9e.camel@gmx.de/
---
 runtest/sched                                 |   1 +
 .../kernel/sched/cfs-scheduler/.gitignore     |   1 +
 .../kernel/sched/cfs-scheduler/starvation.c   | 112 ++++++++++++++++++
 3 files changed, 114 insertions(+)
 create mode 100644 testcases/kernel/sched/cfs-scheduler/starvation.c

Comments

Cyril Hrubis July 13, 2023, 8:58 a.m. UTC | #1
Hi!
> +static long loop = 10000000;

I've reduced the default number of loops to 2000000 since the test
runtime on small ARM board was quite close to the timeout. Given that
when the scheduller was broken the original reproducer haven't finished
after running for 40 times longer than on working kernel, 2000000 should
be enough to trip the timeout even on fairly fast machine.

Also added note to the test description that the test is expected to
timeout when scheduller is broken.

And pushed, thanks.
diff mbox series

Patch

diff --git a/runtest/sched b/runtest/sched
index 592898723..172fe4174 100644
--- a/runtest/sched
+++ b/runtest/sched
@@ -9,6 +9,7 @@  trace_sched01		trace_sched -c 1
 cfs_bandwidth01 cfs_bandwidth01 -i 5
 hackbench01 hackbench 50 process 1000
 hackbench02 hackbench 20 thread 1000
+starvation starvation
 
 sched_cli_serv run_sched_cliserv.sh
 # Run this stress test for 2 minutes
diff --git a/testcases/kernel/sched/cfs-scheduler/.gitignore b/testcases/kernel/sched/cfs-scheduler/.gitignore
index c5dacd6ef..e86178f80 100644
--- a/testcases/kernel/sched/cfs-scheduler/.gitignore
+++ b/testcases/kernel/sched/cfs-scheduler/.gitignore
@@ -1,2 +1,3 @@ 
 /hackbench
 cfs_bandwidth01
+/starvation
diff --git a/testcases/kernel/sched/cfs-scheduler/starvation.c b/testcases/kernel/sched/cfs-scheduler/starvation.c
new file mode 100644
index 000000000..5a3655a3f
--- /dev/null
+++ b/testcases/kernel/sched/cfs-scheduler/starvation.c
@@ -0,0 +1,112 @@ 
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Copyright 2023 Mike Galbraith <efault-AT-gmx.de> */
+/* Copyright 2023 Wei Gao <wegao@suse.com> */
+/*\
+ *
+ * [Description]
+ *
+ * Thread starvation test.
+ * This case copy from following link:
+ * https://lore.kernel.org/lkml/9fd2c37a05713c206dcbd5866f67ce779f315e9e.camel@gmx.de/
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <signal.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <sched.h>
+
+#include "tst_test.h"
+
+static char *str_loop;
+static long loop = 10000000;
+static char *str_timeout;
+static int timeout = 240;
+
+static int wait_for_pid(pid_t pid)
+{
+	int status, ret;
+
+again:
+	ret = waitpid(pid, &status, 0);
+	if (ret == -1) {
+		if (errno == EINTR)
+			goto again;
+
+		return -1;
+	}
+
+	if (WIFSIGNALED(status))
+		return 0;
+
+	return -1;
+}
+
+static void setup(void)
+{
+	cpu_set_t mask;
+
+	CPU_ZERO(&mask);
+
+	CPU_SET(0, &mask);
+
+	TST_EXP_POSITIVE(sched_setaffinity(0, sizeof(mask), &mask));
+
+	if (tst_parse_long(str_loop, &loop, 1, LONG_MAX))
+		tst_brk(TBROK, "Invalid number of loop number '%s'", str_loop);
+
+	if (tst_parse_int(str_timeout, &timeout, 1, INT_MAX))
+		tst_brk(TBROK, "Invalid number of timeout '%s'", str_timeout);
+
+	tst_set_max_runtime(timeout);
+}
+
+static void handler(int sig LTP_ATTRIBUTE_UNUSED)
+{
+	if (loop > 0)
+		--loop;
+}
+
+static void child(void)
+{
+	pid_t ppid = getppid();
+
+	TST_CHECKPOINT_WAIT(0);
+
+	while (1)
+		SAFE_KILL(ppid, SIGUSR1);
+}
+
+static void do_test(void)
+{
+	pid_t child_pid;
+
+	child_pid = SAFE_FORK();
+
+	if (!child_pid)
+		child();
+
+	SAFE_SIGNAL(SIGUSR1, handler);
+	TST_CHECKPOINT_WAKE(0);
+
+	while (loop)
+		sleep(1);
+
+	SAFE_KILL(child_pid, SIGTERM);
+	TST_EXP_PASS(wait_for_pid(child_pid));
+}
+
+static struct tst_test test = {
+	.test_all = do_test,
+	.setup = setup,
+	.forks_child = 1,
+	.options = (struct tst_option[]) {
+		{"l:", &str_loop, "Number of loops (default 10000000)"},
+		{"t:", &str_timeout, "Max timeout (default 240s)"},
+		{}
+	},
+	.needs_checkpoints = 1,
+};