aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/unix/sysv/linux/arm/clone.S
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/unix/sysv/linux/arm/clone.S')
-rw-r--r--sysdeps/unix/sysv/linux/arm/clone.S36
1 files changed, 34 insertions, 2 deletions
diff --git a/sysdeps/unix/sysv/linux/arm/clone.S b/sysdeps/unix/sysv/linux/arm/clone.S
index 8125ebff20..728d62f3e3 100644
--- a/sysdeps/unix/sysv/linux/arm/clone.S
+++ b/sysdeps/unix/sysv/linux/arm/clone.S
@@ -1,5 +1,6 @@
-/* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
This file is part of the GNU C Library.
+ Contributed by Pat Beirne <patb@corelcomputer.com>
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
@@ -27,7 +28,38 @@
.text
ENTRY(__clone)
- /* Somebody needs to write this. */
+ @ sanity check args
+ cmp r0, #0
+ cmpne r1, #0
+ moveq r0, #-EINVAL
+ beq PLTJMP(syscall_error)
+
+ @ insert the args onto the new stack
+ sub r1, r1, #8
+ str r3, [r1, #4]
+ @ save the function pointer as the 0th element
+ str r0, [r1]
+
+ @ do the system call
+ @ get flags
+ mov r0, r2
+ @ new sp is already in r1
+ swi SYS_ify(clone)
+ cmp r0, #0
+ blt PLTJMP(syscall_error)
+ beq thread_start
+ @ else, thread was launched...
+ mov pc, lr
+
+thread_start:
+ @ pick the function arg and call address off the stack and execute
+ ldr r0, [sp, #4]
+ mov lr, pc
+ ldr pc, [sp]
+
+ @ and we are done, passing the return value through r0
+ bl PLTJMP(_exit)
+
PSEUDO_END (__clone)
weak_alias (__clone, clone)