summaryrefslogtreecommitdiffstats
path: root/libc/arch-x86/bionic/clone.S
diff options
context:
space:
mode:
Diffstat (limited to 'libc/arch-x86/bionic/clone.S')
-rw-r--r--libc/arch-x86/bionic/clone.S50
1 files changed, 50 insertions, 0 deletions
diff --git a/libc/arch-x86/bionic/clone.S b/libc/arch-x86/bionic/clone.S
new file mode 100644
index 0000000..361808d
--- /dev/null
+++ b/libc/arch-x86/bionic/clone.S
@@ -0,0 +1,50 @@
+#include <sys/linux-syscalls.h>
+
+.text
+
+/*
+ * int __pthread_clone(int (*fn)(void*), void *tls, int flags,
+ * void *arg);
+ */
+.globl __pthread_clone
+.type __pthread_clone, @function
+.align 4
+__pthread_clone:
+ pushl %ebx
+ pushl %ecx
+ movl 16(%esp), %ecx
+ movl 20(%esp), %ebx
+
+ # insert arguments onto the child stack
+ movl 12(%esp), %eax
+ movl %eax, -12(%ecx)
+ movl 24(%esp), %eax
+ movl %eax, -8(%ecx)
+ lea (%ecx), %eax
+ movl %eax, -4(%ecx)
+
+ movl $__NR_clone, %eax
+ int $0x80
+ test %eax, %eax
+ jns 1f
+
+ # an error occured, set errno and return -1
+ negl %eax
+ call __set_errno
+ orl $-1, %eax
+ jmp 2f
+
+1:
+ jnz 2f
+
+ # we're in the child thread now, call __thread_entry
+ # with the appropriate arguments on the child stack
+ # we already placed most of them
+ subl $16, %esp
+ jmp __thread_entry
+ hlt
+
+2:
+ popl %ecx
+ popl %ebx
+ ret