[LTP] [PATCH v5 2/2] Refactor exit_group01 using new API
Andrea Cervesato
andrea.cervesato@suse.de
Wed Nov 22 15:49:44 CET 2023
From: Andrea Cervesato <andrea.cervesato@suse.com>
We provided a different approach to exit_group() testing, spawning
multiple threads inside the child and checking if they get killed with
the parent process.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
testcases/kernel/syscalls/exit_group/Makefile | 2 +
.../kernel/syscalls/exit_group/exit_group01.c | 161 ++++++++++++------
2 files changed, 112 insertions(+), 51 deletions(-)
diff --git a/testcases/kernel/syscalls/exit_group/Makefile b/testcases/kernel/syscalls/exit_group/Makefile
index 1273a4e9c..adbac3c51 100644
--- a/testcases/kernel/syscalls/exit_group/Makefile
+++ b/testcases/kernel/syscalls/exit_group/Makefile
@@ -3,6 +3,8 @@
top_srcdir ?= ../../../..
+exit_group01: CFLAGS+=-pthread
+
include $(top_srcdir)/include/mk/testcases.mk
include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/exit_group/exit_group01.c b/testcases/kernel/syscalls/exit_group/exit_group01.c
index 5bf5b0218..0fb1b284c 100644
--- a/testcases/kernel/syscalls/exit_group/exit_group01.c
+++ b/testcases/kernel/syscalls/exit_group/exit_group01.c
@@ -1,68 +1,127 @@
-/******************************************************************************
- * Copyright (c) Crackerjack Project., 2007 *
- * Ported to LTP by Manas Kumar Nayak <maknayak@in.ibm.com> *
- * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program 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 General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the Free Software Foundation, *
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
- * *
- ******************************************************************************/
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) Crackerjack Project., 2007
+ * Ported to LTP by Manas Kumar Nayak <maknayak@in.ibm.com>
+ * Copyright (c) 2015 Linux Test Project
+ * Copyright (C) 2015 Cyril Hrubis <chrubis@suse.cz>
+ * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
+ */
-#include <stdio.h>
-#include <errno.h>
-#include <linux/unistd.h>
-#include <sys/wait.h>
+/*\
+ * [Description]
+ *
+ * This test checks if exit_group() correctly ends a spawned child and all its
+ * running threads.
+ */
-#include "test.h"
-#include "safe_macros.h"
+#include <sched.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "tst_test.h"
#include "lapi/syscalls.h"
+#include "tst_safe_pthread.h"
+
+static int cpu_count;
-char *TCID = "exit_group01";
-int testno;
-int TST_TOTAL = 1;
+static struct worker_data {
+ pid_t tid;
+ int counter;
+} *workers_data;
-static void verify_exit_group(void)
+static void *worker(void *arg)
{
- pid_t cpid, w;
- int status;
+ struct worker_data *data;
- cpid = fork();
- if (cpid == -1)
- tst_brkm(TFAIL | TERRNO, NULL, "fork failed");
+ data = (struct worker_data *)arg;
+ data->tid = tst_gettid();
- if (cpid == 0) {
- TEST(tst_syscall(__NR_exit_group, 4));
- } else {
- w = SAFE_WAIT(NULL, &status);
-
- if (WIFEXITED(status) && (WEXITSTATUS(status) == 4)) {
- tst_resm(TPASS, "exit_group() succeeded");
- } else {
- tst_resm(TFAIL | TERRNO,
- "exit_group() failed (wait status = %d)", w);
+ while (1) {
+ tst_atomic_inc(&data->counter);
+ sched_yield();
+ }
+
+ return arg;
+}
+
+static void spawn_threads(void)
+{
+ pthread_t threads[cpu_count];
+
+ for (int i = 0; i < cpu_count; i++)
+ SAFE_PTHREAD_CREATE(&threads[i], NULL, worker, (void *)(workers_data + i));
+}
+
+static void check_counters(void)
+{
+ struct worker_data data_copy[cpu_count];
+
+ memset(data_copy, 0, sizeof(struct worker_data) * cpu_count);
+ memcpy(data_copy, workers_data, sizeof(struct worker_data) * cpu_count);
+
+ tst_res(TINFO, "Checking if threads are still running");
+ usleep(100000);
+
+ struct worker_data *old_data;
+ struct worker_data *new_data;
+
+ for (int i = 0; i < cpu_count; i++) {
+ old_data = data_copy + i;
+ new_data = workers_data + i;
+
+ if (old_data->counter != new_data->counter) {
+ tst_res(TFAIL, "Counter value has changed for thread[%d]", i);
+ return;
}
}
+
+ tst_res(TINFO, "Threads counters value didn't change");
}
-int main(int ac, char **av)
+static void run(void)
{
- int lc;
+ pid_t pid;
+ int status;
+
+ pid = SAFE_FORK();
+ if (!pid) {
+ spawn_threads();
+
+ TEST(tst_syscall(__NR_exit_group, 4));
+ if (TST_RET == -1)
+ tst_brk(TBROK | TERRNO, "exit_group() error");
+
+ return;
+ }
- tst_parse_opts(ac, av, NULL, NULL);
+ SAFE_WAITPID(pid, &status, 0);
- for (lc = 0; TEST_LOOPING(lc); lc++)
- verify_exit_group();
+ TST_EXP_EXPR(WIFEXITED(status) && WEXITSTATUS(status) == 4,
+ "exit_group() succeeded");
- tst_exit();
+ check_counters();
}
+
+static void setup(void)
+{
+ cpu_count = tst_ncpus();
+
+ workers_data = SAFE_MMAP(
+ NULL,
+ sizeof(struct worker_data) * cpu_count,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_ANONYMOUS,
+ -1, 0);
+}
+
+static void cleanup(void)
+{
+ SAFE_MUNMAP(workers_data, sizeof(struct worker_data) * cpu_count);
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .cleanup = cleanup,
+ .test_all = run,
+ .forks_child = 1,
+ .needs_checkpoints = 1,
+};
--
2.35.3
More information about the ltp
mailing list