summaryrefslogtreecommitdiff
path: root/libc/sysdeps/linux/i386
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2004-01-03 08:49:04 +0000
committerEric Andersen <andersen@codepoet.org>2004-01-03 08:49:04 +0000
commitf680861de57542f1ca81de1d7aa8ebb89da1cc2c (patch)
treed7d33af6a5fae404b2a5f5b90691133471c3b11c /libc/sysdeps/linux/i386
parent2d60483b6aa2026b7e56b9adfaf68ffb54dd03c7 (diff)
And just like that, clone is now fixed.... Previously the
error handling code was mostly broken. -Erik
Diffstat (limited to 'libc/sysdeps/linux/i386')
-rw-r--r--libc/sysdeps/linux/i386/clone.S64
1 files changed, 38 insertions, 26 deletions
diff --git a/libc/sysdeps/linux/i386/clone.S b/libc/sysdeps/linux/i386/clone.S
index dd39015fb..1ba3bcc48 100644
--- a/libc/sysdeps/linux/i386/clone.S
+++ b/libc/sysdeps/linux/i386/clone.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996, 1997,98,99,2000,02 Free Software Foundation, Inc.
+/* Copyright (C) 1996,1997,98,99,2000,02,03 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson (rth@tamu.edu)
@@ -18,15 +18,17 @@
02111-1307 USA. */
/* clone() is even more special than fork() as it mucks with stacks
- and invokes a function in the right context after its all over.
-
+ and invokes a function in the right context after its all over.
+
Hacked up for uClibc by Erik Andersen <andersen@codepoet.org>
*/
#define _ERRNO_H 1
#include <features.h>
#include <bits/errno.h>
-#include <sys/syscall.h>
+
+/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
+ pid_t *ptid, struct user_desc *tls, pid_t *ctid); */
#define LINKAGE 4
#define PTR_SIZE 4
@@ -39,6 +41,8 @@
#define TLS PTID+PTR_SIZE
#define CTID TLS+PTR_SIZE
+#define __NR_clone 120
+#define __NR_exit 1
.text
.type clone,@function;
@@ -51,20 +55,13 @@ __clone:
/* Sanity check arguments. */
movl $-EINVAL,%eax
- movl FUNC(%esp),%ecx /* no NULL function pointers */
-#ifdef __PIC__
+ /* no NULL function pointers */
+ movl FUNC(%esp),%ecx
jecxz .Lclone_error
-#else
- testl %ecx,%ecx
- jz .Lclone_error
-#endif
- movl STACK(%esp),%ecx /* no NULL stack pointers */
-#ifdef __PIC__
+
+ /* no NULL stack pointers */
+ movl STACK(%esp),%ecx
jecxz .Lclone_error
-#else
- testl %ecx,%ecx
- jz .Lclone_error
-#endif
/* Insert the argument onto the new stack. Make sure the new
thread is started with an alignment of (mod 16). */
@@ -115,23 +112,38 @@ __clone:
movl $__NR_exit, %eax
int $0x80
+#ifdef __PIC__
+
+.Lthere:
+ movl (%esp), %ebx
+ ret
+
+.Lclone_error:
+ pushl %ebx
+ call .Lthere
+ addl $_GLOBAL_OFFSET_TABLE_, %ebx
+ xorl %edx, %edx
+ subl %eax, %edx
+ pushl %edx
+ call __errno_location@PLT
+ popl %ecx
+ popl %ebx
+ movl %ecx, (%eax)
+ orl $-1, %eax
+ jmp .Lpseudo_end
+
+#else /* __PIC__ */
+
.Lclone_error:
negl %eax
pushl %eax
-#ifdef __PIC__
- call .Lthere
-.Lthere:
- popl %ebx
- addl $_GLOBAL_OFFSET_TABLE_+[.- .Lthere ], %ebx
- call __errno_location@PLT
-#else
call __errno_location
-#endif
popl %ecx
movl %ecx, (%eax)
xorl %eax, %eax
decl %eax
-.Lsize:
- .size __clone,.Lsize-__clone
+#endif
+
+.size __clone,.-__clone