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 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)