• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #define _GNU_SOURCE
2 #include <stdarg.h>
3 #include <unistd.h>
4 #include <sched.h>
5 #include <signal.h>
6 #include "pthread_impl.h"
7 #include "syscall.h"
8 #include "libc.h"
9 
10 struct __clone_args {
11 	int (*func)(void *);
12 	void *arg;
13 };
14 
__start_child(void * clone_args)15 static int __start_child(void *clone_args)
16 {
17 	int status;
18 	sigset_t set;
19 	int (*func)(void *) = ((struct __clone_args *)clone_args)->func;
20 	void *arg = ((struct __clone_args *)clone_args)->arg;
21 
22 	__block_all_sigs(&set);
23 	pthread_t self = __pthread_self();
24 	self->tid = __syscall(SYS_gettid);
25 	self->robust_list.off = 0;
26 	self->robust_list.pending = 0;
27 	self->next = self->prev = self;
28 	__thread_list_lock = 0;
29 	libc.threads_minus_1 = 0;
30 	libc.exit = 0;
31 	signal(SIGSYS, arm_do_signal);
32 	__restore_sigs(&set);
33 
34 	status = func(arg);
35 	exit(status);
36 }
37 
clone(int (* func)(void *),void * stack,int flags,void * arg,...)38 int clone(int (*func)(void *), void *stack, int flags, void *arg, ...)
39 {
40 	int ret;
41 	va_list ap;
42 	pid_t *ptid, *ctid;
43 	void  *tls;
44 	void *mmap_stack = NULL;
45 	void *clone_stack = stack;
46 	int (*clone_func)(void *) = func;
47 	struct __clone_args *clone_args = (struct __clone_args *)arg;
48 
49 	va_start(ap, arg);
50 	ptid = va_arg(ap, pid_t *);
51 	tls  = va_arg(ap, void *);
52 	ctid = va_arg(ap, pid_t *);
53 	va_end(ap);
54 
55 	if (!(flags & (CLONE_VM | CLONE_VFORK))) {
56 		if (func) {
57 			if (!stack) {
58 				mmap_stack = __mmap(0, __default_stacksize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
59 				if (mmap_stack == MAP_FAILED) {
60 					errno = ENOMEM;
61 					return -1;
62 				}
63 				clone_args = (struct __clone_args *)((char *)mmap_stack + __default_stacksize);
64 			} else {
65 				clone_args = (struct __clone_args *)stack;
66  			}
67 			clone_args = (struct __clone_args *)((uintptr_t)clone_args - ((uintptr_t)clone_args % sizeof(uintptr_t)));
68 			clone_args = (struct __clone_args *)((char *)clone_args - sizeof(struct __clone_args));
69 			clone_args->func = clone_func;
70 			clone_args->arg = arg;
71 			clone_func = __start_child;
72 			clone_stack = (void *)clone_args;
73 		}
74 	}
75 	ret = __syscall_ret(__clone(clone_func, clone_stack, flags, (void *)clone_args, ptid, tls, ctid));
76 	if (mmap_stack) {
77 		__munmap(mmap_stack, __default_stacksize);
78 	}
79 	return ret;
80 }
81