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

Reply via email to