1*c9945492SAndroid Build Coastguard Worker #define _GNU_SOURCE
2*c9945492SAndroid Build Coastguard Worker #include <stdarg.h>
3*c9945492SAndroid Build Coastguard Worker #include <unistd.h>
4*c9945492SAndroid Build Coastguard Worker #include <sched.h>
5*c9945492SAndroid Build Coastguard Worker #include "pthread_impl.h"
6*c9945492SAndroid Build Coastguard Worker #include "syscall.h"
7*c9945492SAndroid Build Coastguard Worker #include "lock.h"
8*c9945492SAndroid Build Coastguard Worker #include "fork_impl.h"
9*c9945492SAndroid Build Coastguard Worker
10*c9945492SAndroid Build Coastguard Worker struct clone_start_args {
11*c9945492SAndroid Build Coastguard Worker int (*func)(void *);
12*c9945492SAndroid Build Coastguard Worker void *arg;
13*c9945492SAndroid Build Coastguard Worker sigset_t sigmask;
14*c9945492SAndroid Build Coastguard Worker };
15*c9945492SAndroid Build Coastguard Worker
clone_start(void * arg)16*c9945492SAndroid Build Coastguard Worker static int clone_start(void *arg)
17*c9945492SAndroid Build Coastguard Worker {
18*c9945492SAndroid Build Coastguard Worker struct clone_start_args *csa = arg;
19*c9945492SAndroid Build Coastguard Worker __post_Fork(0);
20*c9945492SAndroid Build Coastguard Worker __restore_sigs(&csa->sigmask);
21*c9945492SAndroid Build Coastguard Worker return csa->func(csa->arg);
22*c9945492SAndroid Build Coastguard Worker }
23*c9945492SAndroid Build Coastguard Worker
clone(int (* func)(void *),void * stack,int flags,void * arg,...)24*c9945492SAndroid Build Coastguard Worker int clone(int (*func)(void *), void *stack, int flags, void *arg, ...)
25*c9945492SAndroid Build Coastguard Worker {
26*c9945492SAndroid Build Coastguard Worker struct clone_start_args csa;
27*c9945492SAndroid Build Coastguard Worker va_list ap;
28*c9945492SAndroid Build Coastguard Worker pid_t *ptid = 0, *ctid = 0;
29*c9945492SAndroid Build Coastguard Worker void *tls = 0;
30*c9945492SAndroid Build Coastguard Worker
31*c9945492SAndroid Build Coastguard Worker /* Flags that produce an invalid thread/TLS state are disallowed. */
32*c9945492SAndroid Build Coastguard Worker int badflags = CLONE_THREAD | CLONE_SETTLS | CLONE_CHILD_CLEARTID;
33*c9945492SAndroid Build Coastguard Worker
34*c9945492SAndroid Build Coastguard Worker if ((flags & badflags) || !stack)
35*c9945492SAndroid Build Coastguard Worker return __syscall_ret(-EINVAL);
36*c9945492SAndroid Build Coastguard Worker
37*c9945492SAndroid Build Coastguard Worker va_start(ap, arg);
38*c9945492SAndroid Build Coastguard Worker if (flags & (CLONE_PIDFD | CLONE_PARENT_SETTID | CLONE_CHILD_SETTID))
39*c9945492SAndroid Build Coastguard Worker ptid = va_arg(ap, pid_t *);
40*c9945492SAndroid Build Coastguard Worker if (flags & CLONE_CHILD_SETTID) {
41*c9945492SAndroid Build Coastguard Worker tls = va_arg(ap, void *);
42*c9945492SAndroid Build Coastguard Worker ctid = va_arg(ap, pid_t *);
43*c9945492SAndroid Build Coastguard Worker }
44*c9945492SAndroid Build Coastguard Worker va_end(ap);
45*c9945492SAndroid Build Coastguard Worker
46*c9945492SAndroid Build Coastguard Worker /* If CLONE_VM is used, it's impossible to give the child a consistent
47*c9945492SAndroid Build Coastguard Worker * thread structure. In this case, the best we can do is assume the
48*c9945492SAndroid Build Coastguard Worker * caller is content with an extremely restrictive execution context
49*c9945492SAndroid Build Coastguard Worker * like the one vfork() would provide. */
50*c9945492SAndroid Build Coastguard Worker if (flags & CLONE_VM) return __syscall_ret(
51*c9945492SAndroid Build Coastguard Worker __clone(func, stack, flags, arg, ptid, tls, ctid));
52*c9945492SAndroid Build Coastguard Worker
53*c9945492SAndroid Build Coastguard Worker __block_all_sigs(&csa.sigmask);
54*c9945492SAndroid Build Coastguard Worker LOCK(__abort_lock);
55*c9945492SAndroid Build Coastguard Worker
56*c9945492SAndroid Build Coastguard Worker /* Setup the a wrapper start function for the child process to do
57*c9945492SAndroid Build Coastguard Worker * mimic _Fork in producing a consistent execution state. */
58*c9945492SAndroid Build Coastguard Worker csa.func = func;
59*c9945492SAndroid Build Coastguard Worker csa.arg = arg;
60*c9945492SAndroid Build Coastguard Worker int ret = __clone(clone_start, stack, flags, &csa, ptid, tls, ctid);
61*c9945492SAndroid Build Coastguard Worker
62*c9945492SAndroid Build Coastguard Worker __post_Fork(ret);
63*c9945492SAndroid Build Coastguard Worker __restore_sigs(&csa.sigmask);
64*c9945492SAndroid Build Coastguard Worker return __syscall_ret(ret);
65*c9945492SAndroid Build Coastguard Worker }
66