! 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 #include /* 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