Linux-kselftest Archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 07/15] selftests/sched: Add a test to verify that DL server works with core scheduling
       [not found] <20240313012451.1693807-1-joel@joelfernandes.org>
@ 2024-03-13  1:24 ` Joel Fernandes (Google)
  2024-03-13  1:24 ` [PATCH v2 08/15] selftests/sched: Migrate cs_prctl_test to kselfttest Joel Fernandes (Google)
  1 sibling, 0 replies; 3+ messages in thread
From: Joel Fernandes (Google) @ 2024-03-13  1:24 UTC (permalink / raw
  To: linux-kernel, Shuah Khan, Nathan Chancellor, Nick Desaulniers,
	Bill Wendling, Justin Stitt
  Cc: Suleiman Souhlal, Youssef Esmat, Steven Rostedt, David Vernet,
	Thomas Gleixner, Paul E . McKenney, joseph.salisbury,
	Dietmar Eggemann, Ben Segall, Mel Gorman,
	Daniel Bristot de Oliveira, Valentin Schneider, Luca Abeni,
	Tommaso Cucinotta, Vineeth Pillai, Shuah Khan, Phil Auld,
	Joel Fernandes (Google), linux-kselftest, llvm

This test verifies that DL server infrastructure gives CFS tasks a fixed
bandwidth even when RT tasks are being "core scheduled" on a core.
Verify that they are getting the expected bandwidth (and thus not being
starved).

Also verified that not having core scheduling fixes makes the test fail
as the CFS task gets no bandwidth.

Sample output:

 # Runtime of PID 97 is 4.440000 seconds
 # Runtime of PID 98 is 4.560000 seconds
 # Runtime of PID 99 is 4.550000 seconds
 ok 1 PASS

Notes about test that generated the sample output:

The test runs for 12 seconds. We check the runtimes at 9 seconds. We
expect the CFS task (PID 7) to get ~50% of the 9 seconds. The DL server
is configured for 50% bandwidth.

The RT tasks (PID 98, 99) each get 50% as well, because they run
concurrently on 2 hyperthreads of a core.

Signed-off-by: Joel Fernandes (Google) <joel@joelfernandes.org>
---
 tools/testing/selftests/sched/Makefile        |  13 +-
 tools/testing/selftests/sched/common.c        |  24 ++
 tools/testing/selftests/sched/common.h        |   8 +
 .../selftests/sched/cs_dlserver_test.c        | 254 ++++++++++++++++++
 4 files changed, 290 insertions(+), 9 deletions(-)
 create mode 100644 tools/testing/selftests/sched/common.c
 create mode 100644 tools/testing/selftests/sched/common.h
 create mode 100644 tools/testing/selftests/sched/cs_dlserver_test.c

diff --git a/tools/testing/selftests/sched/Makefile b/tools/testing/selftests/sched/Makefile
index 099ee9213557..f491d741cb45 100644
--- a/tools/testing/selftests/sched/Makefile
+++ b/tools/testing/selftests/sched/Makefile
@@ -1,14 +1,9 @@
 # SPDX-License-Identifier: GPL-2.0+
+TEST_GEN_PROGS := cs_dlserver_test
 
-ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),)
-CLANG_FLAGS += -no-integrated-as
-endif
+cs_dlserver_test: cs_dlserver_test.c common.c
 
-CFLAGS += -O2 -Wall -g -I./ $(KHDR_INCLUDES) -Wl,-rpath=./ \
-	  $(CLANG_FLAGS)
-LDLIBS += -lpthread
-
-TEST_GEN_FILES := cs_prctl_test
-TEST_PROGS := cs_prctl_test
+CFLAGS += $(KHDR_INCLUDES)
+CFLAGS += -Wall
 
 include ../lib.mk
diff --git a/tools/testing/selftests/sched/common.c b/tools/testing/selftests/sched/common.c
new file mode 100644
index 000000000000..5cf0022acc8d
--- /dev/null
+++ b/tools/testing/selftests/sched/common.c
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include "common.h"
+
+bool hyperthreading_enabled(void)
+{
+	FILE *file = fopen("/sys/devices/system/cpu/smt/active", "r");
+	char smt_active[2];
+
+	if (file == NULL) {
+		ksft_print_msg("Could not determine if hyperthreading is enabled\n");
+		return false;
+	}
+
+	if (fgets(smt_active, sizeof(smt_active), file)	== NULL) {
+		perror("Failed to read smt_active");
+		return false;
+	}
+	fclose(file);
+
+	if (smt_active[0] != '1')
+		return false;
+	return true;
+}
diff --git a/tools/testing/selftests/sched/common.h b/tools/testing/selftests/sched/common.h
new file mode 100644
index 000000000000..7bcedbd0ed99
--- /dev/null
+++ b/tools/testing/selftests/sched/common.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <dirent.h>
+#include "../kselftest.h"
+
+bool hyperthreading_enabled(void);
diff --git a/tools/testing/selftests/sched/cs_dlserver_test.c b/tools/testing/selftests/sched/cs_dlserver_test.c
new file mode 100644
index 000000000000..9f2a74a25686
--- /dev/null
+++ b/tools/testing/selftests/sched/cs_dlserver_test.c
@@ -0,0 +1,254 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Use the DL server infrastructure to give CFS tasks a fixed bandwidth
+ * even when RT tasks are being "core scheduled" on a core. Verify that
+ * they are getting the expected bandwidth (and thus not being starved).
+ *
+ * Copyright (c) 2024 Google.
+ * Author: Joel Fernandes <joel@joelfernandes.org>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of version 2.1 of the GNU Lesser General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see <http://www.gnu.org/licenses>.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sched.h>
+#include <time.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <sys/prctl.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include "common.h"
+
+enum pid_type {PIDTYPE_PID = 0, PIDTYPE_TGID, PIDTYPE_PGID};
+
+#define RUN_TIME 12 // Running time of the test in seconds
+#define CORE_ID 0 // Assuming we're pinning processes to the first core
+#define DL_SERVER_DEBUGFS "/sys/kernel/debug/sched/fair_server"
+
+void write_server_debugfs(char *file, char *type, unsigned long value)
+{
+	char path[1024], buf[1024];
+	int fd, n;
+
+	snprintf(path, sizeof(path), "%s/%s/%s", DL_SERVER_DEBUGFS, file, type);
+	fd = open(path,	O_WRONLY);
+	if (fd == -1) {
+		perror("Failed to open file for writing");
+		return;
+	}
+	n = snprintf(buf, sizeof(buf), "%lu\n", value);
+	n = write(fd, buf, n);
+	if (n == -1)
+		perror("Failed to write file");
+
+	close(fd);
+}
+
+void write_dl_server_params(void)
+{
+	DIR *dir;
+	struct dirent *entry;
+
+	if (access(DL_SERVER_DEBUGFS, F_OK) == -1) {
+		perror("DL server debugfs not found, cannot set DL parameters.");
+		exit(EXIT_FAILURE);
+	}
+
+	dir = opendir(DL_SERVER_DEBUGFS);
+	if (dir	== NULL) {
+		perror("Failed to open directory");
+		exit(EXIT_FAILURE);
+	}
+
+	while ((entry = readdir(dir)) != NULL) {
+		if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
+			continue;
+
+		write_server_debugfs(entry->d_name, "period", 100000000);
+		write_server_debugfs(entry->d_name, "runtime", 50000000);
+	}
+	closedir(dir);
+}
+
+void process_func(void)
+{
+	unsigned long long count = 0;
+	time_t end;
+
+	// Busy loop for RUN_TIME seconds
+	end = time(NULL) + RUN_TIME;
+	while (time(NULL) < end) {
+		count++; // Just a dummy operation
+	}
+}
+
+void set_affinity(int cpu_id)
+{
+	cpu_set_t cpuset;
+
+	CPU_ZERO(&cpuset);
+	CPU_SET(cpu_id, &cpuset);
+	CPU_SET(cpu_id + 1, &cpuset);
+
+	if (sched_setaffinity(0, sizeof(cpu_set_t), &cpuset) != 0) {
+		perror("sched_setaffinity");
+		exit(EXIT_FAILURE);
+	}
+}
+
+void set_sched(int policy, int priority)
+{
+	struct sched_param param;
+
+	param.sched_priority = priority;
+	if (sched_setscheduler(0, policy, &param) != 0) {
+		perror("sched_setscheduler");
+		exit(EXIT_FAILURE);
+	}
+}
+
+float get_process_runtime(int pid)
+{
+	char path[256];
+	FILE *file;
+	long utime, stime;
+	int fields;
+
+	snprintf(path, sizeof(path), "/proc/%d/stat", pid);
+	file = fopen(path, "r");
+	if (file == NULL) {
+		perror("Failed to open stat file");
+		return -1; // Indicate failure
+	}
+
+	// Skip the first 13 fields and read the 14th and 15th
+	fields = fscanf(file,
+					"%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %lu %lu",
+					&utime, &stime);
+	fclose(file);
+
+	if (fields != 2) {
+		fprintf(stderr, "Failed to read stat file\n");
+		return -1; // Indicate failure
+	}
+
+	// Calculate the total time spent in the process
+	long total_time = utime + stime;
+	long ticks_per_second = sysconf(_SC_CLK_TCK);
+	float runtime_seconds = total_time * 1.0 / ticks_per_second;
+
+	return runtime_seconds;
+}
+
+int main(void)
+{
+	float runtime1, runtime2, runtime3;
+	int pid1, pid2, pid3;
+
+	if (!hyperthreading_enabled())
+		ksft_test_result_skip("This test requires hyperthreading to be enabled\n");
+
+	write_dl_server_params();
+
+	ksft_print_header();
+	ksft_set_plan(1);
+
+	// Create and set up a CFS task
+	pid1 = fork();
+	if (pid1 == 0) {
+		set_affinity(CORE_ID);
+		process_func();
+		exit(0);
+	} else if (pid1 < 0) {
+		perror("fork for p1");
+		ksft_exit_fail();
+	}
+
+	// Create a new unique cookie for the CFS task
+	if (prctl(PR_SCHED_CORE, PR_SCHED_CORE_CREATE, pid1, PIDTYPE_TGID, 0) < 0) {
+		perror("prctl for pid1");
+		ksft_exit_fail();
+	}
+
+	// Create a new unique cookie for the current process. Future
+	// forks will inherit this cookie.
+	if (prctl(PR_SCHED_CORE, PR_SCHED_CORE_CREATE, 0, PIDTYPE_TGID, 0) < 0) {
+		perror("prctl for current process");
+		ksft_exit_fail();
+	}
+
+	// Create an RT task which inherits the parent's cookie
+	pid2 = fork();
+	if (pid2 == 0) {
+		set_affinity(CORE_ID);
+		set_sched(SCHED_FIFO, 50);
+		process_func();
+		exit(0);
+	} else if (pid2 < 0) {
+		perror("fork for p2");
+		ksft_exit_fail();
+	}
+
+	// Create another RT task which inherits the parent's cookie
+	pid3 = fork();
+	if (pid3 == 0) {
+		set_affinity(CORE_ID);
+		set_sched(SCHED_FIFO, 50);
+		process_func();
+		exit(0);
+	} else if (pid3 < 0) {
+		perror("fork for p3");
+		ksft_exit_fail();
+	}
+
+	sleep(RUN_TIME * 3 / 4);
+	runtime1 = get_process_runtime(pid1);
+	if (runtime1 != -1)
+		ksft_print_msg("Runtime of PID %d is %f seconds\n", pid1, runtime1);
+	else
+		ksft_exit_fail_msg("Error getting runtime for PID %d\n", pid1);
+
+	runtime2 = get_process_runtime(pid2);
+	if (runtime2 != -1)
+		ksft_print_msg("Runtime of PID %d is %f seconds\n", pid2, runtime2);
+	else
+		ksft_exit_fail_msg("Error getting runtime for PID %d\n", pid2);
+
+	runtime3 = get_process_runtime(pid3);
+	if (runtime3 != -1)
+		ksft_print_msg("Runtime of PID %d is %f seconds\n", pid3, runtime3);
+	else
+		ksft_exit_fail_msg("Error getting runtime for PID %d\n", pid3);
+
+	// Make sure runtime1 is within 30% of runtime2
+	if (runtime1 < 0.7 * runtime2 || runtime1 > 1.3	* runtime2)
+		ksft_exit_fail_msg("Runtime of PID %d is not within 30%% of runtime of PID %d\n",
+						   pid1, pid2);
+
+	// Make	sure runtime1 is within 30% of runtime3
+	if (runtime1 < 0.7 * runtime3 || runtime1 > 1.3 * runtime3)
+		ksft_exit_fail_msg("Runtime of PID %d is not within 30%% of runtime of PID %d\n",
+						   pid1, pid3);
+
+	waitpid(pid1, NULL, 0);
+	waitpid(pid2, NULL, 0);
+	waitpid(pid3, NULL, 0);
+
+	ksft_test_result_pass("PASS\n");
+	return 0;
+}
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH v2 08/15] selftests/sched: Migrate cs_prctl_test to kselfttest
       [not found] <20240313012451.1693807-1-joel@joelfernandes.org>
  2024-03-13  1:24 ` [PATCH v2 07/15] selftests/sched: Add a test to verify that DL server works with core scheduling Joel Fernandes (Google)
@ 2024-03-13  1:24 ` Joel Fernandes (Google)
  2024-03-13 18:44   ` Chris Hyser
  1 sibling, 1 reply; 3+ messages in thread
From: Joel Fernandes (Google) @ 2024-03-13  1:24 UTC (permalink / raw
  To: linux-kernel, Shuah Khan
  Cc: Suleiman Souhlal, Youssef Esmat, Steven Rostedt, David Vernet,
	Thomas Gleixner, Paul E . McKenney, joseph.salisbury,
	Dietmar Eggemann, Ben Segall, Mel Gorman,
	Daniel Bristot de Oliveira, Valentin Schneider, Luca Abeni,
	Tommaso Cucinotta, Vineeth Pillai, Shuah Khan, Phil Auld,
	Joel Fernandes (Google), linux-kselftest

This test begs to be a kselftest, is in the kselftest hierarchy and does
not even use a single kselftest API. Convert it.

It simplifies some of the code and the output also looks much nicer now:

 Totals: pass:17 fail:0 xfail:0 xpass:0 skip:0 error:0

Signed-off-by: Joel Fernandes (Google) <joel@joelfernandes.org>
---
 tools/testing/selftests/sched/Makefile        |  6 +-
 tools/testing/selftests/sched/cs_prctl_test.c | 74 ++++++++++---------
 2 files changed, 43 insertions(+), 37 deletions(-)

diff --git a/tools/testing/selftests/sched/Makefile b/tools/testing/selftests/sched/Makefile
index f491d741cb45..90c53bc1337e 100644
--- a/tools/testing/selftests/sched/Makefile
+++ b/tools/testing/selftests/sched/Makefile
@@ -1,9 +1,11 @@
 # SPDX-License-Identifier: GPL-2.0+
 TEST_GEN_PROGS := cs_dlserver_test
-
-cs_dlserver_test: cs_dlserver_test.c common.c
+TEST_GEN_PROGS += cs_prctl_test
 
 CFLAGS += $(KHDR_INCLUDES)
 CFLAGS += -Wall
 
 include ../lib.mk
+
+$(OUTPUT)/cs_dlserver_test: cs_dlserver_test.c common.c
+$(OUTPUT)/cs_prctl_test: cs_prctl_test.c common.c
diff --git a/tools/testing/selftests/sched/cs_prctl_test.c b/tools/testing/selftests/sched/cs_prctl_test.c
index 7ba057154343..bb7aee703cdf 100644
--- a/tools/testing/selftests/sched/cs_prctl_test.c
+++ b/tools/testing/selftests/sched/cs_prctl_test.c
@@ -28,10 +28,11 @@
 #include <unistd.h>
 #include <time.h>
 #include <errno.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
+#include "common.h"
+
 #if __GLIBC_PREREQ(2, 30) == 0
 #include <sys/syscall.h>
 static pid_t gettid(void)
@@ -80,7 +81,7 @@ static int _prctl(int option, unsigned long arg2, unsigned long arg3, unsigned l
 	int res;
 
 	res = prctl(option, arg2, arg3, arg4, arg5);
-	printf("%d = prctl(%d, %ld, %ld, %ld, %lx)\n", res, option, (long)arg2, (long)arg3,
+	ksft_print_msg("%d = prctl(%d, %ld, %ld, %ld, %lx)\n", res, option, (long)arg2, (long)arg3,
 	       (long)arg4, arg5);
 	return res;
 }
@@ -91,21 +92,20 @@ static int _prctl(int option, unsigned long arg2, unsigned long arg3, unsigned l
 static void __handle_error(char *fn, int ln, char *msg)
 {
 	int pidx;
-	printf("(%s:%d) - ", fn, ln);
+	ksft_print_msg("(%s:%d) - ", fn, ln);
 	perror(msg);
 	if (need_cleanup) {
 		for (pidx = 0; pidx < num_processes; ++pidx)
 			kill(procs[pidx].cpid, 15);
 		need_cleanup = 0;
 	}
-	exit(EXIT_FAILURE);
+	ksft_exit_fail();
 }
 
 static void handle_usage(int rc, char *msg)
 {
-	puts(USAGE);
-	puts(msg);
-	putchar('\n');
+	ksft_print_msg("%s\n", USAGE);
+	ksft_print_msg("%s\n\n", msg);
 	exit(rc);
 }
 
@@ -117,7 +117,7 @@ static unsigned long get_cs_cookie(int pid)
 	ret = prctl(PR_SCHED_CORE, PR_SCHED_CORE_GET, pid, PIDTYPE_PID,
 		    (unsigned long)&cookie);
 	if (ret) {
-		printf("Not a core sched system\n");
+		ksft_print_msg("Not a core sched system\n");
 		return -1UL;
 	}
 
@@ -160,7 +160,7 @@ static int child_func_process(void *arg)
 
 	ret = write(ca->pfd[1], &ca->thr_tids, sizeof(int) * ca->num_threads);
 	if (ret == -1)
-		printf("write failed on pfd[%d] - error (%s)\n",
+		ksft_print_msg("write failed on pfd[%d] - error (%s)\n",
 			ca->pfd[1], strerror(errno));
 
 	close(ca->pfd[1]);
@@ -192,7 +192,7 @@ void create_processes(int num_processes, int num_threads, struct child_args proc
 	for (i = 0; i < num_processes; ++i) {
 		ret = read(proc[i].pfd[0], &proc[i].thr_tids, sizeof(int) * proc[i].num_threads);
 		if (ret == -1)
-			printf("read failed on proc[%d].pfd[0] error (%s)\n",
+			ksft_print_msg("read failed on proc[%d].pfd[0] error (%s)\n",
 				i, strerror(errno));
 		close(proc[i].pfd[0]);
 	}
@@ -202,30 +202,29 @@ void disp_processes(int num_processes, struct child_args proc[])
 {
 	int i, j;
 
-	printf("tid=%d, / tgid=%d / pgid=%d: %lx\n", gettid(), getpid(), getpgid(0),
+	ksft_print_msg("tid=%d, / tgid=%d / pgid=%d: %lx\n", gettid(), getpid(), getpgid(0),
 	       get_cs_cookie(getpid()));
 
 	for (i = 0; i < num_processes; ++i) {
-		printf("    tid=%d, / tgid=%d / pgid=%d: %lx\n", proc[i].cpid, proc[i].cpid,
+		ksft_print_msg("    tid=%d, / tgid=%d / pgid=%d: %lx\n", proc[i].cpid, proc[i].cpid,
 		       getpgid(proc[i].cpid), get_cs_cookie(proc[i].cpid));
 		for (j = 0; j < proc[i].num_threads; ++j) {
-			printf("        tid=%d, / tgid=%d / pgid=%d: %lx\n", proc[i].thr_tids[j],
+			ksft_print_msg("        tid=%d, / tgid=%d / pgid=%d: %lx\n", proc[i].thr_tids[j],
 			       proc[i].cpid, getpgid(0), get_cs_cookie(proc[i].thr_tids[j]));
 		}
 	}
 	puts("\n");
 }
 
-static int errors;
-
 #define validate(v) _validate(__LINE__, v, #v)
 void _validate(int line, int val, char *msg)
 {
 	if (!val) {
-		++errors;
-		printf("(%d) FAILED: %s\n", line, msg);
+		ksft_print_msg("(%d) FAILED: %s\n", line, msg);
+		ksft_inc_fail_cnt();
 	} else {
-		printf("(%d) PASSED: %s\n", line, msg);
+		ksft_print_msg("(%d) PASSED: %s\n", line, msg);
+		ksft_inc_pass_cnt();
 	}
 }
 
@@ -254,13 +253,17 @@ int main(int argc, char *argv[])
 			keypress = 1;
 			break;
 		case 'h':
-			printf(USAGE);
+			ksft_print_msg(USAGE);
 			exit(EXIT_SUCCESS);
 		default:
 			handle_usage(20, "unknown option");
 		}
 	}
 
+	if (!hyperthreading_enabled()) {
+		ksft_exit_skip("This test requires hyperthreading to be enabled\n");
+	}
+
 	if (num_processes < 1 || num_processes > MAX_PROCESSES)
 		handle_usage(1, "Bad processes value");
 
@@ -272,17 +275,22 @@ int main(int argc, char *argv[])
 
 	srand(time(NULL));
 
-	/* put into separate process group */
+	/* Put into separate process group */
 	if (setpgid(0, 0) != 0)
 		handle_error("process group");
 
-	printf("\n## Create a thread/process/process group hiearchy\n");
+	ksft_print_header();
+
+	/* Increase the count if adding more validate() statements. */
+	ksft_set_plan(17);
+
+	ksft_print_msg("\n## Create a thread/process/process group hiearchy\n");
 	create_processes(num_processes, num_threads, procs);
 	need_cleanup = 1;
 	disp_processes(num_processes, procs);
 	validate(get_cs_cookie(0) == 0);
 
-	printf("\n## Set a cookie on entire process group\n");
+	ksft_print_msg("\n## Set a cookie on entire process group\n");
 	if (_prctl(PR_SCHED_CORE, PR_SCHED_CORE_CREATE, 0, PIDTYPE_PGID, 0) < 0)
 		handle_error("core_sched create failed -- PGID");
 	disp_processes(num_processes, procs);
@@ -296,7 +304,7 @@ int main(int argc, char *argv[])
 	validate(get_cs_cookie(0) == get_cs_cookie(pid));
 	validate(get_cs_cookie(0) == get_cs_cookie(procs[pidx].thr_tids[0]));
 
-	printf("\n## Set a new cookie on entire process/TGID [%d]\n", pid);
+	ksft_print_msg("\n## Set a new cookie on entire process/TGID [%d]\n", pid);
 	if (_prctl(PR_SCHED_CORE, PR_SCHED_CORE_CREATE, pid, PIDTYPE_TGID, 0) < 0)
 		handle_error("core_sched create failed -- TGID");
 	disp_processes(num_processes, procs);
@@ -305,7 +313,7 @@ int main(int argc, char *argv[])
 	validate(get_cs_cookie(pid) != 0);
 	validate(get_cs_cookie(pid) == get_cs_cookie(procs[pidx].thr_tids[0]));
 
-	printf("\n## Copy the cookie of current/PGID[%d], to pid [%d] as PIDTYPE_PID\n",
+	ksft_print_msg("\n## Copy the cookie of current/PGID[%d], to pid [%d] as PIDTYPE_PID\n",
 	       getpid(), pid);
 	if (_prctl(PR_SCHED_CORE, PR_SCHED_CORE_SHARE_TO, pid, PIDTYPE_PID, 0) < 0)
 		handle_error("core_sched share to itself failed -- PID");
@@ -315,7 +323,7 @@ int main(int argc, char *argv[])
 	validate(get_cs_cookie(pid) != 0);
 	validate(get_cs_cookie(pid) != get_cs_cookie(procs[pidx].thr_tids[0]));
 
-	printf("\n## Copy cookie from a thread [%d] to current/PGID [%d] as PIDTYPE_PID\n",
+	ksft_print_msg("\n## Copy cookie from a thread [%d] to current/PGID [%d] as PIDTYPE_PID\n",
 	       procs[pidx].thr_tids[0], getpid());
 	if (_prctl(PR_SCHED_CORE, PR_SCHED_CORE_SHARE_FROM, procs[pidx].thr_tids[0],
 		   PIDTYPE_PID, 0) < 0)
@@ -325,7 +333,7 @@ int main(int argc, char *argv[])
 	validate(get_cs_cookie(0) == get_cs_cookie(procs[pidx].thr_tids[0]));
 	validate(get_cs_cookie(pid) != get_cs_cookie(procs[pidx].thr_tids[0]));
 
-	printf("\n## Copy cookie from current [%d] to current as pidtype PGID\n", getpid());
+	ksft_print_msg("\n## Copy cookie from current [%d] to current as pidtype PGID\n", getpid());
 	if (_prctl(PR_SCHED_CORE, PR_SCHED_CORE_SHARE_TO, 0, PIDTYPE_PGID, 0) < 0)
 		handle_error("core_sched share to self failed -- PGID");
 	disp_processes(num_processes, procs);
@@ -340,20 +348,16 @@ int main(int argc, char *argv[])
 	validate(_prctl(PR_SCHED_CORE, PR_SCHED_CORE_SHARE_TO, 0, PIDTYPE_PGID, 1) < 0
 		&& errno == EINVAL);
 
-	if (errors) {
-		printf("TESTS FAILED. errors: %d\n", errors);
-		res = 10;
-	} else {
-		printf("SUCCESS !!!\n");
-	}
-
-	if (keypress)
+	if (keypress) {
+		ksft_print_msg("Waiting for keypress to exit\n");
 		getchar();
-	else
+	} else {
 		sleep(delay);
+	}
 
 	for (pidx = 0; pidx < num_processes; ++pidx)
 		kill(procs[pidx].cpid, 15);
 
+	ksft_finished();
 	return res;
 }
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH v2 08/15] selftests/sched: Migrate cs_prctl_test to kselfttest
  2024-03-13  1:24 ` [PATCH v2 08/15] selftests/sched: Migrate cs_prctl_test to kselfttest Joel Fernandes (Google)
@ 2024-03-13 18:44   ` Chris Hyser
  0 siblings, 0 replies; 3+ messages in thread
From: Chris Hyser @ 2024-03-13 18:44 UTC (permalink / raw
  To: Joel Fernandes (Google), linux-kernel, Shuah Khan
  Cc: Suleiman Souhlal, Youssef Esmat, Steven Rostedt, David Vernet,
	Thomas Gleixner, Paul E . McKenney, joseph.salisbury,
	Dietmar Eggemann, Ben Segall, Mel Gorman,
	Daniel Bristot de Oliveira, Valentin Schneider, Luca Abeni,
	Tommaso Cucinotta, Vineeth Pillai, Shuah Khan, Phil Auld,
	linux-kselftest


On 3/12/24 21:24, Joel Fernandes (Google) wrote:
> This test begs to be a kselftest, is in the kselftest hierarchy and does
> not even use a single kselftest API. Convert it.
>
> It simplifies some of the code and the output also looks much nicer now:
>
>   Totals: pass:17 fail:0 xfail:0 xpass:0 skip:0 error:0
>
> Signed-off-by: Joel Fernandes (Google) <joel@joelfernandes.org>

Reviewed-by: Chris Hyser <chris.hyser@oracle.com>


> ---
>   tools/testing/selftests/sched/Makefile        |  6 +-
>   tools/testing/selftests/sched/cs_prctl_test.c | 74 ++++++++++---------
>   2 files changed, 43 insertions(+), 37 deletions(-)
>
> diff --git a/tools/testing/selftests/sched/Makefile b/tools/testing/selftests/sched/Makefile
> index f491d741cb45..90c53bc1337e 100644
> --- a/tools/testing/selftests/sched/Makefile
> +++ b/tools/testing/selftests/sched/Makefile
> @@ -1,9 +1,11 @@
>   # SPDX-License-Identifier: GPL-2.0+
>   TEST_GEN_PROGS := cs_dlserver_test
> -
> -cs_dlserver_test: cs_dlserver_test.c common.c
> +TEST_GEN_PROGS += cs_prctl_test
>   
>   CFLAGS += $(KHDR_INCLUDES)
>   CFLAGS += -Wall
>   
>   include ../lib.mk
> +
> +$(OUTPUT)/cs_dlserver_test: cs_dlserver_test.c common.c
> +$(OUTPUT)/cs_prctl_test: cs_prctl_test.c common.c
> diff --git a/tools/testing/selftests/sched/cs_prctl_test.c b/tools/testing/selftests/sched/cs_prctl_test.c
> index 7ba057154343..bb7aee703cdf 100644
> --- a/tools/testing/selftests/sched/cs_prctl_test.c
> +++ b/tools/testing/selftests/sched/cs_prctl_test.c
> @@ -28,10 +28,11 @@
>   #include <unistd.h>
>   #include <time.h>
>   #include <errno.h>
> -#include <stdio.h>
>   #include <stdlib.h>
>   #include <string.h>
>   
> +#include "common.h"
> +
>   #if __GLIBC_PREREQ(2, 30) == 0
>   #include <sys/syscall.h>
>   static pid_t gettid(void)
> @@ -80,7 +81,7 @@ static int _prctl(int option, unsigned long arg2, unsigned long arg3, unsigned l
>   	int res;
>   
>   	res = prctl(option, arg2, arg3, arg4, arg5);
> -	printf("%d = prctl(%d, %ld, %ld, %ld, %lx)\n", res, option, (long)arg2, (long)arg3,
> +	ksft_print_msg("%d = prctl(%d, %ld, %ld, %ld, %lx)\n", res, option, (long)arg2, (long)arg3,
>   	       (long)arg4, arg5);
>   	return res;
>   }
> @@ -91,21 +92,20 @@ static int _prctl(int option, unsigned long arg2, unsigned long arg3, unsigned l
>   static void __handle_error(char *fn, int ln, char *msg)
>   {
>   	int pidx;
> -	printf("(%s:%d) - ", fn, ln);
> +	ksft_print_msg("(%s:%d) - ", fn, ln);
>   	perror(msg);
>   	if (need_cleanup) {
>   		for (pidx = 0; pidx < num_processes; ++pidx)
>   			kill(procs[pidx].cpid, 15);
>   		need_cleanup = 0;
>   	}
> -	exit(EXIT_FAILURE);
> +	ksft_exit_fail();
>   }
>   
>   static void handle_usage(int rc, char *msg)
>   {
> -	puts(USAGE);
> -	puts(msg);
> -	putchar('\n');
> +	ksft_print_msg("%s\n", USAGE);
> +	ksft_print_msg("%s\n\n", msg);
>   	exit(rc);
>   }
>   
> @@ -117,7 +117,7 @@ static unsigned long get_cs_cookie(int pid)
>   	ret = prctl(PR_SCHED_CORE, PR_SCHED_CORE_GET, pid, PIDTYPE_PID,
>   		    (unsigned long)&cookie);
>   	if (ret) {
> -		printf("Not a core sched system\n");
> +		ksft_print_msg("Not a core sched system\n");
>   		return -1UL;
>   	}
>   
> @@ -160,7 +160,7 @@ static int child_func_process(void *arg)
>   
>   	ret = write(ca->pfd[1], &ca->thr_tids, sizeof(int) * ca->num_threads);
>   	if (ret == -1)
> -		printf("write failed on pfd[%d] - error (%s)\n",
> +		ksft_print_msg("write failed on pfd[%d] - error (%s)\n",
>   			ca->pfd[1], strerror(errno));
>   
>   	close(ca->pfd[1]);
> @@ -192,7 +192,7 @@ void create_processes(int num_processes, int num_threads, struct child_args proc
>   	for (i = 0; i < num_processes; ++i) {
>   		ret = read(proc[i].pfd[0], &proc[i].thr_tids, sizeof(int) * proc[i].num_threads);
>   		if (ret == -1)
> -			printf("read failed on proc[%d].pfd[0] error (%s)\n",
> +			ksft_print_msg("read failed on proc[%d].pfd[0] error (%s)\n",
>   				i, strerror(errno));
>   		close(proc[i].pfd[0]);
>   	}
> @@ -202,30 +202,29 @@ void disp_processes(int num_processes, struct child_args proc[])
>   {
>   	int i, j;
>   
> -	printf("tid=%d, / tgid=%d / pgid=%d: %lx\n", gettid(), getpid(), getpgid(0),
> +	ksft_print_msg("tid=%d, / tgid=%d / pgid=%d: %lx\n", gettid(), getpid(), getpgid(0),
>   	       get_cs_cookie(getpid()));
>   
>   	for (i = 0; i < num_processes; ++i) {
> -		printf("    tid=%d, / tgid=%d / pgid=%d: %lx\n", proc[i].cpid, proc[i].cpid,
> +		ksft_print_msg("    tid=%d, / tgid=%d / pgid=%d: %lx\n", proc[i].cpid, proc[i].cpid,
>   		       getpgid(proc[i].cpid), get_cs_cookie(proc[i].cpid));
>   		for (j = 0; j < proc[i].num_threads; ++j) {
> -			printf("        tid=%d, / tgid=%d / pgid=%d: %lx\n", proc[i].thr_tids[j],
> +			ksft_print_msg("        tid=%d, / tgid=%d / pgid=%d: %lx\n", proc[i].thr_tids[j],
>   			       proc[i].cpid, getpgid(0), get_cs_cookie(proc[i].thr_tids[j]));
>   		}
>   	}
>   	puts("\n");
>   }
>   
> -static int errors;
> -
>   #define validate(v) _validate(__LINE__, v, #v)
>   void _validate(int line, int val, char *msg)
>   {
>   	if (!val) {
> -		++errors;
> -		printf("(%d) FAILED: %s\n", line, msg);
> +		ksft_print_msg("(%d) FAILED: %s\n", line, msg);
> +		ksft_inc_fail_cnt();
>   	} else {
> -		printf("(%d) PASSED: %s\n", line, msg);
> +		ksft_print_msg("(%d) PASSED: %s\n", line, msg);
> +		ksft_inc_pass_cnt();
>   	}
>   }
>   
> @@ -254,13 +253,17 @@ int main(int argc, char *argv[])
>   			keypress = 1;
>   			break;
>   		case 'h':
> -			printf(USAGE);
> +			ksft_print_msg(USAGE);
>   			exit(EXIT_SUCCESS);
>   		default:
>   			handle_usage(20, "unknown option");
>   		}
>   	}
>   
> +	if (!hyperthreading_enabled()) {
> +		ksft_exit_skip("This test requires hyperthreading to be enabled\n");
> +	}
> +
>   	if (num_processes < 1 || num_processes > MAX_PROCESSES)
>   		handle_usage(1, "Bad processes value");
>   
> @@ -272,17 +275,22 @@ int main(int argc, char *argv[])
>   
>   	srand(time(NULL));
>   
> -	/* put into separate process group */
> +	/* Put into separate process group */
>   	if (setpgid(0, 0) != 0)
>   		handle_error("process group");
>   
> -	printf("\n## Create a thread/process/process group hiearchy\n");
> +	ksft_print_header();
> +
> +	/* Increase the count if adding more validate() statements. */
> +	ksft_set_plan(17);
> +
> +	ksft_print_msg("\n## Create a thread/process/process group hiearchy\n");
>   	create_processes(num_processes, num_threads, procs);
>   	need_cleanup = 1;
>   	disp_processes(num_processes, procs);
>   	validate(get_cs_cookie(0) == 0);
>   
> -	printf("\n## Set a cookie on entire process group\n");
> +	ksft_print_msg("\n## Set a cookie on entire process group\n");
>   	if (_prctl(PR_SCHED_CORE, PR_SCHED_CORE_CREATE, 0, PIDTYPE_PGID, 0) < 0)
>   		handle_error("core_sched create failed -- PGID");
>   	disp_processes(num_processes, procs);
> @@ -296,7 +304,7 @@ int main(int argc, char *argv[])
>   	validate(get_cs_cookie(0) == get_cs_cookie(pid));
>   	validate(get_cs_cookie(0) == get_cs_cookie(procs[pidx].thr_tids[0]));
>   
> -	printf("\n## Set a new cookie on entire process/TGID [%d]\n", pid);
> +	ksft_print_msg("\n## Set a new cookie on entire process/TGID [%d]\n", pid);
>   	if (_prctl(PR_SCHED_CORE, PR_SCHED_CORE_CREATE, pid, PIDTYPE_TGID, 0) < 0)
>   		handle_error("core_sched create failed -- TGID");
>   	disp_processes(num_processes, procs);
> @@ -305,7 +313,7 @@ int main(int argc, char *argv[])
>   	validate(get_cs_cookie(pid) != 0);
>   	validate(get_cs_cookie(pid) == get_cs_cookie(procs[pidx].thr_tids[0]));
>   
> -	printf("\n## Copy the cookie of current/PGID[%d], to pid [%d] as PIDTYPE_PID\n",
> +	ksft_print_msg("\n## Copy the cookie of current/PGID[%d], to pid [%d] as PIDTYPE_PID\n",
>   	       getpid(), pid);
>   	if (_prctl(PR_SCHED_CORE, PR_SCHED_CORE_SHARE_TO, pid, PIDTYPE_PID, 0) < 0)
>   		handle_error("core_sched share to itself failed -- PID");
> @@ -315,7 +323,7 @@ int main(int argc, char *argv[])
>   	validate(get_cs_cookie(pid) != 0);
>   	validate(get_cs_cookie(pid) != get_cs_cookie(procs[pidx].thr_tids[0]));
>   
> -	printf("\n## Copy cookie from a thread [%d] to current/PGID [%d] as PIDTYPE_PID\n",
> +	ksft_print_msg("\n## Copy cookie from a thread [%d] to current/PGID [%d] as PIDTYPE_PID\n",
>   	       procs[pidx].thr_tids[0], getpid());
>   	if (_prctl(PR_SCHED_CORE, PR_SCHED_CORE_SHARE_FROM, procs[pidx].thr_tids[0],
>   		   PIDTYPE_PID, 0) < 0)
> @@ -325,7 +333,7 @@ int main(int argc, char *argv[])
>   	validate(get_cs_cookie(0) == get_cs_cookie(procs[pidx].thr_tids[0]));
>   	validate(get_cs_cookie(pid) != get_cs_cookie(procs[pidx].thr_tids[0]));
>   
> -	printf("\n## Copy cookie from current [%d] to current as pidtype PGID\n", getpid());
> +	ksft_print_msg("\n## Copy cookie from current [%d] to current as pidtype PGID\n", getpid());
>   	if (_prctl(PR_SCHED_CORE, PR_SCHED_CORE_SHARE_TO, 0, PIDTYPE_PGID, 0) < 0)
>   		handle_error("core_sched share to self failed -- PGID");
>   	disp_processes(num_processes, procs);
> @@ -340,20 +348,16 @@ int main(int argc, char *argv[])
>   	validate(_prctl(PR_SCHED_CORE, PR_SCHED_CORE_SHARE_TO, 0, PIDTYPE_PGID, 1) < 0
>   		&& errno == EINVAL);
>   
> -	if (errors) {
> -		printf("TESTS FAILED. errors: %d\n", errors);
> -		res = 10;
> -	} else {
> -		printf("SUCCESS !!!\n");
> -	}
> -
> -	if (keypress)
> +	if (keypress) {
> +		ksft_print_msg("Waiting for keypress to exit\n");
>   		getchar();
> -	else
> +	} else {
>   		sleep(delay);
> +	}
>   
>   	for (pidx = 0; pidx < num_processes; ++pidx)
>   		kill(procs[pidx].cpid, 15);
>   
> +	ksft_finished();
>   	return res;
>   }

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2024-03-13 18:44 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20240313012451.1693807-1-joel@joelfernandes.org>
2024-03-13  1:24 ` [PATCH v2 07/15] selftests/sched: Add a test to verify that DL server works with core scheduling Joel Fernandes (Google)
2024-03-13  1:24 ` [PATCH v2 08/15] selftests/sched: Migrate cs_prctl_test to kselfttest Joel Fernandes (Google)
2024-03-13 18:44   ` Chris Hyser

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).