1853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy/*
2853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy * Copyright (c) 2013 Fujitsu Ltd.
3853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy * Author: Zeng Linggang <zenglg.jy@cn.fujitsu.com>
4853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy *
5853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy * This program is free software; you can redistribute it and/or modify it
6853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy * under the terms of version 2 of the GNU General Public License as
7853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy * published by the Free Software Foundation.
8853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy *
9853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy * This program is distributed in the hope that it would be useful, but
10853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy * WITHOUT ANY WARRANTY; without even the implied warranty of
11853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy *
13853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy * You should have received a copy of the GNU General Public License along
14853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy * with this program.
15853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy */
16853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
1750a1afe70594d7b8cbf0086e77fb1be9e154beb5Cyril Hrubis#define _GNU_SOURCE
18853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy#include <errno.h>
19853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy#include <sched.h>
20853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy#include <sys/wait.h>
21853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy#include "test.h"
22853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy#include "clone_platform.h"
23853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy#include "safe_macros.h"
24853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy#include "linux_syscall_numbers.h"
25853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
261db62666ceab32282807215bb2882a3cfa5979fdZeng Linggangchar *TCID = "clone08";
271db62666ceab32282807215bb2882a3cfa5979fdZeng Linggang
28853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jystatic pid_t ptid, ctid, tgid;
29853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jystatic void *child_stack;
30853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
31853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jystatic void setup(void);
32853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jystatic void cleanup(void);
33853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
34853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jystatic void test_clone_parent(int t);
35853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jystatic int child_clone_parent(void);
36853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jystatic pid_t parent_ppid;
37853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
38853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jystatic void test_clone_tid(int t);
39853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jystatic int child_clone_child_settid(void);
40853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jystatic int child_clone_parent_settid(void);
41853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
42853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy#ifdef CLONE_STOPPED
43853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jystatic void test_clone_stopped(int t);
44853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jystatic int child_clone_stopped(void);
45853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jystatic int stopped_flag;
46853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy#endif
47853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
48853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jystatic void test_clone_thread(int t);
49853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jystatic int child_clone_thread(void);
50853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jystatic int tst_result;
51853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
52853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy/*
53853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy * Children cloned with CLONE_VM should avoid using any functions that
54853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy * might require dl_runtime_resolve, because they share thread-local
55853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy * storage with parent. If both try to resolve symbols at same time you
56853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy * can crash, likely at _dl_x86_64_restore_sse().
57853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy * See this thread for relevant discussion:
58853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy * http://www.mail-archive.com/utrace-devel@redhat.com/msg01944.html
59853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy */
60853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jystatic struct test_case {
61853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	char *name;
62853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	int flags;
63853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	void (*testfunc)(int);
64853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	int (*do_child)();
65853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy} test_cases[] = {
66853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	{"CLONE_PARENT", CLONE_PARENT | SIGCHLD,
67853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	 test_clone_parent, child_clone_parent},
68853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	{"CLONE_CHILD_SETTID", CLONE_CHILD_SETTID | SIGCHLD,
69853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	 test_clone_tid, child_clone_child_settid},
70853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	{"CLONE_PARENT_SETTID", CLONE_PARENT_SETTID | CLONE_VM | SIGCHLD,
71853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	 test_clone_tid, child_clone_parent_settid},
72853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy#ifdef CLONE_STOPPED
73853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	{"CLONE_STOPPED", CLONE_STOPPED | CLONE_VM | SIGCHLD,
74853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	 test_clone_stopped, child_clone_stopped},
75853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy#endif
76853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	{"CLONE_THREAD", CLONE_THREAD | CLONE_SIGHAND | CLONE_VM | SIGCHLD,
77853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	 test_clone_thread, child_clone_thread},
78853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy};
79853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
80853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jyint TST_TOTAL = ARRAY_SIZE(test_cases);
81853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
82853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jyint main(int ac, char **av)
83853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy{
84853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	int i, lc;
85853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
86d6d11d08678aac1ed2c370ea8e42e5f45aea07beCyril Hrubis	tst_parse_opts(ac, av, NULL, NULL);
87853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
88853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	setup();
89853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	for (lc = 0; TEST_LOOPING(lc); lc++) {
90853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		tst_count = 0;
91853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		for (i = 0; i < TST_TOTAL; i++) {
92853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy			tst_resm(TINFO, "running %s", test_cases[i].name);
93853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy			test_cases[i].testfunc(i);
94853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		}
95853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	}
96853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	cleanup();
97853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	tst_exit();
98853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy}
99853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
100853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jystatic void setup(void)
101853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy{
102853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	tst_sig(FORK, DEF_HANDLER, cleanup);
103853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
104853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	TEST_PAUSE;
105853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
106853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	tst_tmpdir();
107853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
108853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	child_stack = SAFE_MALLOC(cleanup, CHILD_STACK_SIZE);
109853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy}
110853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
111853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jystatic void cleanup(void)
112853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy{
113853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	free(child_stack);
114853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
115853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	tst_rmdir();
116853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy}
117853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
118853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jystatic long clone_child(const struct test_case *t, int use_tst)
119853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy{
1201db62666ceab32282807215bb2882a3cfa5979fdZeng Linggang	TEST(ltp_clone7(t->flags, t->do_child, NULL, CHILD_STACK_SIZE,
121853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		child_stack, &ptid, NULL, &ctid));
1221db62666ceab32282807215bb2882a3cfa5979fdZeng Linggang
1231db62666ceab32282807215bb2882a3cfa5979fdZeng Linggang	if (TEST_RETURN == -1 && TTERRNO == ENOSYS)
1241db62666ceab32282807215bb2882a3cfa5979fdZeng Linggang		tst_brkm(TCONF, cleanup, "clone does not support 7 args");
1251db62666ceab32282807215bb2882a3cfa5979fdZeng Linggang
126853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	if (TEST_RETURN == -1) {
127853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		if (use_tst) {
128853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy			tst_brkm(TBROK | TTERRNO, cleanup, "%s clone() failed",
129853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy				 t->name);
130853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		} else {
131853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy			printf("%s clone() failed, errno: %d",
132853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy			       t->name, TEST_ERRNO);
133853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy			exit(1);
134853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		}
135853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	}
136853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	return TEST_RETURN;
137853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy}
138853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
139853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jystatic int wait4child(pid_t child)
140853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy{
141853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	int status;
142853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
143853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	if (waitpid(child, &status, 0) == -1)
144853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		tst_resm(TBROK|TERRNO, "waitpid");
145853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	if (WIFEXITED(status))
146853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		return WEXITSTATUS(status);
147853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	else
148853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		return status;
149853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy}
150853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
151853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jystatic void test_clone_parent(int t)
152853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy{
153853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	int status;
154853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	pid_t child;
155853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
156853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	fflush(stdout);
157853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	child = FORK_OR_VFORK();
158853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	switch (child) {
159853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	case 0:
160853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		parent_ppid = getppid();
161853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		clone_child(&test_cases[t], 0);
162853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		exit(0);
163853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	case -1:
164853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		tst_brkm(TBROK | TERRNO, NULL, "test_clone_parent fork");
165853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	default:
166853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		status = wait4child(child);
167853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		if (status == 0) {
168853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy			/* wait for CLONE_PARENT child */
169853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy			status = wait4child(-1);
170853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy			if (status == 0) {
171853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy				tst_resm(TPASS, "test %s", test_cases[t].name);
172853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy			} else {
173853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy				tst_resm(TFAIL, "test %s, status: %d",
174853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy					 test_cases[t].name, status);
175853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy			}
176853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		} else {
177853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy			tst_resm(TFAIL, "test %s, status: %d",
178853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy				 test_cases[t].name, status);
179853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		}
180853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	};
181853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy}
182853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
183853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jystatic int child_clone_parent(void)
184853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy{
185853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	if (parent_ppid == getppid())
186853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		exit(0);
187853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	printf("FAIL: getppid != parent_ppid (%d != %d)\n",
188853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	       parent_ppid, getppid());
189853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	exit(1);
190853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy}
191853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
192853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jystatic void test_clone_tid(int t)
193853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy{
194853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	int status;
195853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	pid_t child;
196853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
197853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	child = clone_child(&test_cases[t], 1);
198853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	status = wait4child(child);
199853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	if (status == 0) {
200853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		tst_resm(TPASS, "test %s", test_cases[t].name);
201853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	} else {
202853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		tst_resm(TFAIL, "test %s, status: %d",
203853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy			 test_cases[t].name, status);
204853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	}
205853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy}
206853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
207853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jystatic int child_clone_child_settid(void)
208853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy{
209853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	if (ctid == ltp_syscall(__NR_getpid))
210853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		ltp_syscall(__NR_exit, 0);
211853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	printf("FAIL: ctid != getpid() (%d != %d)\n",
212853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	       ctid, getpid());
213853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	ltp_syscall(__NR_exit, 1);
214853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	return 0;
215853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy}
216853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
217853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jystatic int child_clone_parent_settid(void)
218853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy{
219853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	if (ptid == ltp_syscall(__NR_getpid))
220853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		ltp_syscall(__NR_exit, 0);
221853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	printf("FAIL: ptid != getpid() (%d != %d)\n",
222853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	       ptid, getpid());
223853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	ltp_syscall(__NR_exit, 1);
224853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	return 0;
225853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy}
226853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
227853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy#ifdef CLONE_STOPPED
228853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jystatic void test_clone_stopped(int t)
229853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy{
230853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	int i;
231853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	int status;
232853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	int flag;
233853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	pid_t child;
234853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
235dc054fbc2a0efee8abfa395e0a5ea817896023f9Shuang Qiu	if (tst_kvercmp(2, 6, 38) >= 0) {
236dc054fbc2a0efee8abfa395e0a5ea817896023f9Shuang Qiu		tst_resm(TINFO, "CLONE_STOPPED skipped for kernels >= 2.6.38");
237dc054fbc2a0efee8abfa395e0a5ea817896023f9Shuang Qiu		return;
238dc054fbc2a0efee8abfa395e0a5ea817896023f9Shuang Qiu	}
239dc054fbc2a0efee8abfa395e0a5ea817896023f9Shuang Qiu
240853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	stopped_flag = 0;
241853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	child = clone_child(&test_cases[t], 1);
242853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
243853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	/* give the kernel scheduler chance to run the CLONE_STOPPED thread*/
244853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	for (i = 0; i < 100; i++) {
245853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		sched_yield();
246853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		usleep(1000);
247853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	}
248853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
249853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	flag = stopped_flag;
250853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	if (kill(child, SIGCONT) != 0)
251853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		tst_brkm(TBROK | TERRNO, cleanup, "kill SIGCONT failed");
252853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
253853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	status = wait4child(child);
254853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	if (status == 0 && flag == 0) {
255853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		tst_resm(TPASS, "test %s", test_cases[t].name);
256853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	} else {
257853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		tst_resm(TFAIL, "test %s, status: %d, flag: %d",
258853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy			 test_cases[t].name, status, flag);
259853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	}
260853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy}
261853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
262853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jystatic int child_clone_stopped(void)
263853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy{
264853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	stopped_flag = 1;
265853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	ltp_syscall(__NR_exit, 0);
266853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	return 0;
267853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy}
268853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy#endif
269853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
270853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jystatic void test_clone_thread(int t)
271853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy{
272853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	pid_t child;
273853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	int i, status;
274853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
275853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	fflush(stdout);
276853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	child = FORK_OR_VFORK();
277853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	switch (child) {
278853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	case 0:
279853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		tgid = ltp_syscall(__NR_getpid);
280853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		tst_result = -1;
281853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		clone_child(&test_cases[t], 0);
282853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
283853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		for (i = 0; i < 5000; i++) {
284853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy			sched_yield();
285853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy			usleep(1000);
286853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy			if (tst_result != -1)
287853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy				break;
288853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		}
289853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		ltp_syscall(__NR_exit, tst_result);
290853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	case -1:
291853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		tst_brkm(TBROK | TERRNO, NULL, "test_clone_thread fork");
292853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	default:
293853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		status = wait4child(child);
294853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		if (status == 0) {
295853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy			tst_resm(TPASS, "test %s", test_cases[t].name);
296853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		} else {
297853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy			tst_resm(TFAIL, "test %s, status: %d",
298853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy				 test_cases[t].name, status);
299853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		}
300853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	};
301853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy}
302853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy
303853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jystatic int child_clone_thread(void)
304853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy{
305853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	if (tgid == ltp_syscall(__NR_getpid))
306853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		tst_result = TPASS;
307853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	else
308853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy		tst_result = TFAIL;
309853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	ltp_syscall(__NR_exit, 0);
310853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy	return 0;
311853f9811db8ef4a948e70df9b81ed219de7e842ezenglg.jy}
312