1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465 |
- ! Copyright (C) 2013 Imagination Technologies Ltd.
- ! Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
- ! clone() is even more special than fork() as it mucks with stacks
- ! and invokes a function in the right context after its all over.
- #include <asm/errno.h>
- #include <asm/unistd.h>
- /* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */
- .text
- .global __clone
- .type __clone,function
- __clone:
- ! sanity check args
- MOV D0Re0, #-EINVAL
- CMP D1Ar1, #0
- BEQ ___error
- CMP D0Ar2, #0
- BEQ ___error
- ! save function pointer
- MOV D0FrT, D1Ar1
- ! do the system call
- ! get flags
- MOV D1Ar1, D1Ar3
- ! new sp is already in D0Ar2
- MOV D1Re0, #__NR_clone
- SWITCH #0x440001
- CMP D0Re0,#0
- ! Error on -1
- BLT ___error
- ! If non-zero we are the parent
- MOVNE PC, D1RtP
- ! BRKPNT
- ! We are the child
- ! pick the function arg and call address off the stack and execute
- MOV D0Ar2, D0FrT
- MOV D1Ar1, D0Ar4
- MOV D1RtP, PC
- ADD D1RtP, D1RtP, #8
- MOV PC, D0Ar2
- ! and we are done, passing the return value through D0Re0
- #ifdef __PIC__
- B _exit@PLT
- #else
- B _exit
- #endif
- ___error:
- MOV D1Ar1, D0Re0
- #ifdef __PIC__
- B ___syscall_error@PLT
- #else
- B ___syscall_error
- #endif
- .size __clone, .-__clone
- .weak _clone
- _clone = __clone
|