Add new case for clone(2) with CLONE_PARENT, CLONE_CHILD_SETTID, CLONE_PARENT_SETTID, CLONE_STOPPED, CLONE_THREAD.
Signed-off-by: Zeng Linggang <[email protected]> --- runtest/ltplite | 1 + runtest/stress.part3 | 1 + runtest/syscalls | 1 + testcases/kernel/syscalls/.gitignore | 1 + testcases/kernel/syscalls/clone/clone08.c | 238 ++++++++++++++++++++++++++++++ 5 files changed, 242 insertions(+) create mode 100644 testcases/kernel/syscalls/clone/clone08.c diff --git a/runtest/ltplite b/runtest/ltplite index f0738c7..71dbb5e 100644 --- a/runtest/ltplite +++ b/runtest/ltplite @@ -126,6 +126,7 @@ clone04 clone04 clone05 clone05 clone06 clone06 clone07 clone07 +clone08 clone08 close01 close01 close02 close02 diff --git a/runtest/stress.part3 b/runtest/stress.part3 index 951b00e..8c42e1b 100644 --- a/runtest/stress.part3 +++ b/runtest/stress.part3 @@ -67,6 +67,7 @@ clone04 clone04 clone05 clone05 clone06 clone06 clone07 clone07 +clone08 clone08 close01 close01 close02 close02 diff --git a/runtest/syscalls b/runtest/syscalls index e5a5508..33cb11c 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -84,6 +84,7 @@ clone04 clone04 clone05 clone05 clone06 clone06 clone07 clone07 +clone08 clone08 close01 close01 close02 close02 diff --git a/testcases/kernel/syscalls/.gitignore b/testcases/kernel/syscalls/.gitignore index 0effa6b..35dd2c5 100644 --- a/testcases/kernel/syscalls/.gitignore +++ b/testcases/kernel/syscalls/.gitignore @@ -64,6 +64,7 @@ /clone/clone05 /clone/clone06 /clone/clone07 +/clone/clone08 /close/close01 /close/close02 /close/close08 diff --git a/testcases/kernel/syscalls/clone/clone08.c b/testcases/kernel/syscalls/clone/clone08.c new file mode 100644 index 0000000..8eebb4d --- /dev/null +++ b/testcases/kernel/syscalls/clone/clone08.c @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2013 Fujitsu Ltd. + * Author: Zeng Linggang <[email protected]> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <errno.h> +#include <linux/sched.h> +#include <sched.h> +#include <sys/wait.h> +#include "test.h" +#include "usctest.h" +#include "clone_platform.h" +#include "linux_syscall_numbers.h" +#include "safe_macros.h" + +#define PASS 0 +#define FAIL 1 +#define SIG_PASS SIGUSR1 +#define SIG_FAIL SIGUSR2 + + +static pid_t parent_ppid; +static pid_t ptid, ctid; +static pid_t tgid; +static void *child_stack; +static int test_index; + +static void setup(void); +static void cleanup(void); + +static int child_clone_parent(void); +static int child_clone_child_settid(void); +static int child_clone_parent_settid(void); +static int child_clone_thread(void); + +static void test_clone_parent_settid(int tid); +static void sig_func(int signo); + +#ifdef CLONE_STOPPED +static int thread_state; +static void test_clone_stopped(int tid); +static int child_clone_stopped(void); +#endif + +static int notwait_flag = CLONE_PARENT | CLONE_THREAD; +static struct test_case { + char *name; + int flags; + void (*testfunc)(int tid); + int (*do_child)(); +} test_cases[] = { + {"CLONE_PARENT", CLONE_PARENT, NULL, child_clone_parent}, + {"CLONE_CHILD_SETTID", CLONE_CHILD_SETTID | SIGCHLD, NULL, + child_clone_child_settid}, + {"CLONE_PARENT_SETTID", CLONE_PARENT_SETTID | SIGCHLD, + test_clone_parent_settid, child_clone_parent_settid}, +#ifdef CLONE_STOPPED + {"CLONE_STOPPED", CLONE_STOPPED | SIGCHLD, test_clone_stopped, + child_clone_stopped}, +#endif + {"CLONE_THREAD", CLONE_THREAD | CLONE_SIGHAND | CLONE_VM, NULL, + child_clone_thread}, +}; + +char *TCID = "clone08"; +int TST_TOTAL = ARRAY_SIZE(test_cases); + +int main(int ac, char **av) +{ + int lc; + int i = 0; + int status; + + setup(); + + for (lc = 0; TEST_LOOPING(lc); lc++) { + tst_count = 0; + + for (i = 0; i < TST_TOTAL; i++) { + test_index = i; + TEST(ltp_clone(test_cases[i].flags, + test_cases[i].do_child, + NULL, CHILD_STACK_SIZE, child_stack, + &ptid, NULL, &ctid)); + + if (TEST_RETURN == -1) { + tst_brkm(TFAIL | TTERRNO, cleanup, + "%s clone() failed", + test_cases[i].name); + continue; + } + + if (test_cases[i].testfunc != NULL) + test_cases[i].testfunc(TEST_RETURN); + + if ((test_cases[i].flags & notwait_flag) == 0) { + if (wait(&status) == -1) { + tst_brkm(TBROK | TERRNO, cleanup, + "wait failed, status: %d", + status); + } + if (test_cases[i].testfunc != NULL) + continue; + if (WIFEXITED(status) && + WEXITSTATUS(status) == PASS) { + tst_resm(TPASS, "test %s success", + test_cases[i].name); + } else { + tst_resm(TFAIL, "test %s fail", + test_cases[i].name); + } + } else { + /* + * wait cloned thread to wake us, and verify + * the test result in the signal hander + */ + pause(); + } + } + } + + cleanup(); + tst_exit(); +} + +static void setup(void) +{ + tst_sig(FORK, DEF_HANDLER, cleanup); + TEST_PAUSE; + + parent_ppid = getppid(); + tgid = getpid(); + + if (signal(SIG_PASS, sig_func) == SIG_ERR) + tst_brkm(TBROK | TERRNO, cleanup, "signal failed"); + if (signal(SIG_FAIL, sig_func) == SIG_ERR) + tst_brkm(TBROK | TERRNO, cleanup, "signal failed"); + + child_stack = SAFE_MALLOC(cleanup, CHILD_STACK_SIZE); +} + +static void cleanup(void) +{ + free(child_stack); + + TEST_CLEANUP; +} + +static int child_clone_parent() +{ + usleep(500000); + if (parent_ppid == getppid()) + kill(tgid, SIG_PASS); + else + kill(tgid, SIG_FAIL); + exit(PASS); +} + +static void sig_func(int signo) +{ + if (signo != SIG_PASS) + tst_resm(TFAIL, "test %s fail", test_cases[test_index].name); + else + tst_resm(TPASS, "test %s success", test_cases[test_index].name); +} + +static int child_clone_child_settid() +{ + if (ctid != getpid()) + exit(FAIL); + else + exit(PASS); +} + +static void test_clone_parent_settid(int tid) +{ + if (tid != ptid) + tst_resm(TFAIL, "test CLONE_PARENT_SETTID fail"); + else + tst_resm(TPASS, "test CLONE_PARENT_SETTID success"); +} + +static int child_clone_parent_settid() +{ + exit(PASS); +} + +#ifdef CLONE_STOPPED +static void test_clone_stopped(int tid) +{ + int i; + + /* give the kernel scheduler chance to run the child */ + for (i = 0; i < 100; i++) { + sched_yield(); + usleep(1000); + } + if (thread_state == 0) + tst_resm(TPASS, "test CLONE_STOPPED success"); + else + tst_resm(TFAIL, "test CLONE_STOPPED fail"); + + if (kill(tid, SIGCONT) != 0) + tst_brkm(TBROK | TERRNO, cleanup, "kill SIGCONT failed"); +} + +static int child_clone_stopped() +{ + thread_state = 1; + exit(PASS); +} +#endif + +static int child_clone_thread(void) +{ + pid_t child_tgid; + + child_tgid = getpid(); + + if (tgid == child_tgid) + kill(tgid, SIG_PASS); + else + kill(tgid, SIG_FAIL); + usleep(500000); + exit(PASS); +} -- 1.8.2.1 ------------------------------------------------------------------------------ Shape the Mobile Experience: Free Subscription Software experts and developers: Be at the forefront of tech innovation. Intel(R) Software Adrenaline delivers strategic insight and game-changing conversations that shape the rapidly evolving mobile landscape. Sign up now. http://pubads.g.doubleclick.net/gampad/clk?id=63431311&iu=/4140/ostg.clktrk _______________________________________________ Ltp-list mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/ltp-list
