X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/2d21ac55c334faf3a56e5634905ed6987fc787d4..13f56ec4e58bf8687e2a68032c093c0213dd519b:/libsyscall/custom/__fork.s diff --git a/libsyscall/custom/__fork.s b/libsyscall/custom/__fork.s index 227812ecc..2de3a9a28 100644 --- a/libsyscall/custom/__fork.s +++ b/libsyscall/custom/__fork.s @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2007 Apple Inc. All rights reserved. + * Copyright (c) 1999-2010 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -36,104 +36,26 @@ * 11-Jan-92 Peter King (king@next.com) * Created from M68K sources */ - -#include "SYS.h" - -#if defined(__ppc__) || defined(__ppc64__) - -/* We use mode-independent "g" opcodes such as "srgi". These expand - * into word operations when targeting __ppc__, and into doubleword - * operations when targeting __ppc64__. - */ -#include - -MI_ENTRY_POINT(___fork) - MI_PUSH_STACK_FRAME - - MI_CALL_EXTERNAL(__cthread_fork_prepare) - - li r0,SYS_fork - sc // do the fork - b Lbotch // error return - - cmpwi r4,0 // parent (r4==0) or child (r4==1) ? - beq Lparent // parent, since r4==0 - - -/* Here if we are the child. */ - -#if defined(__DYNAMIC__) - .cstring -LC3: - .ascii "__dyld_fork_child\0" - .text - .align 2 - mflr r0 - bcl 20,31,1f -1: mflr r3 - mtlr r0 - addis r3,r3,ha16(LC3-1b) - addi r3,r3,lo16(LC3-1b) - addi r4,r1,SF_LOCAL1 - bl __dyld_func_lookup - lg r3,SF_LOCAL1(r1) - mtspr ctr,r3 - bctrl -#endif - - li r9,0 - MI_GET_ADDRESS(r8,__current_pid) - stw r9,0(r8) // clear cached pid in child - - MI_CALL_EXTERNAL(__cthread_fork_child) - - li r3,0 // flag for "we are the child" - b Lreturn - - -/* Here if we are the parent, with: - * r3 = child's pid + +/* + * All of the asm stubs in this file have been adjusted so the pre/post + * fork handlers and dyld fixup are done in C inside Libc. As such, Libc + * expects the __fork asm to fix up the return code to be -1, 0 or pid + * and errno if needed. */ -Lparent: - stg r3,SF_LOCAL2(r1) // save child pid in stack - - b Lparent_return // clean up and return child's pid - - -/* Here if the fork() syscall failed. We're still the parent. */ - -Lbotch: - MI_CALL_EXTERNAL(cerror) - li r3,-1 // get an error return code - stg r3,SF_LOCAL2(r1) // save return code in stack - - /* - * We use cthread_fork_parent() to clean up after a fork error - * (unlock cthreads and mailloc packages) so the parent - * process can Malloc() after fork() errors without - * deadlocking. - */ - -Lparent_return: - MI_CALL_EXTERNAL(__cthread_fork_parent) - lg r3,SF_LOCAL2(r1) // return -1 on error, child's pid on success - -Lreturn: - MI_POP_STACK_FRAME_AND_RETURN +#include "SYS.h" -#elif defined(__i386__) +#if defined(__i386__) LEAF(___fork, 0) subl $28, %esp // Align the stack, with 16 bytes of extra padding that we'll need - CALL_EXTERN(__cthread_fork_prepare) movl $ SYS_fork,%eax; // code for fork -> eax UNIX_SYSCALL_TRAP // do the system call jnc L1 // jump if CF==0 CALL_EXTERN(cerror) - CALL_EXTERN(__cthread_fork_parent) movl $-1,%eax addl $28, %esp // restore the stack ret @@ -143,60 +65,23 @@ L1: jz L2 // parent, since r1 == 0 in parent, 1 in child //child here... -#if defined(__DYNAMIC__) -// Here on the child side of the fork we need to tell the dynamic linker that -// we have forked. To do this we call __dyld_fork_child in the dyanmic -// linker. But since we can't dynamically bind anything until this is done we -// do this by using the private extern __dyld_func_lookup() function to get the -// address of __dyld_fork_child (the 'C' code equivlent): -// -// _dyld_func_lookup("__dyld_fork_child", &address); -// address(); -// -.cstring -LC0: - .ascii "__dyld_fork_child\0" - -.text - leal 0x8(%esp),%eax // get the address where we're going to store the pointer - movl %eax, 0x4(%esp) // copy the address of the pointer - call 1f -1: popl %eax - leal LC0-1b(%eax),%eax - movl %eax, 0x0(%esp) // copy the name of the function to look up - call __dyld_func_lookup - movl 0x8(%esp),%eax // move the value returned in address parameter - call *%eax // call __dyld_fork_child indirectly -#endif - xorl %eax, %eax - REG_TO_EXTERN(%eax, __current_pid) - CALL_EXTERN(__cthread_fork_child) - xorl %eax,%eax // zero eax - addl $28, %esp // restore the stack - ret - - //parent here... + REG_TO_EXTERN(%eax, __current_pid); L2: - movl %eax, 0xc(%esp) // save pid - - CALL_EXTERN_AGAIN(__cthread_fork_parent) - movl 0xc(%esp), %eax // return pid addl $28, %esp // restore the stack - ret + // parent ends up here skipping child portion + ret #elif defined(__x86_64__) LEAF(___fork, 0) subq $24, %rsp // Align the stack, plus room for local storage - CALL_EXTERN(__cthread_fork_prepare) movl $ SYSCALL_CONSTRUCT_UNIX(SYS_fork),%eax; // code for fork -> rax UNIX_SYSCALL_TRAP // do the system call jnc L1 // jump if CF==0 CALL_EXTERN(cerror) - CALL_EXTERN(__cthread_fork_parent) movq $-1, %rax addq $24, %rsp // restore the stack ret @@ -206,106 +91,13 @@ L1: jz L2 // parent, since r1 == 0 in parent, 1 in child //child here... -#if defined(__DYNAMIC__) -// Here on the child side of the fork we need to tell the dynamic linker that -// we have forked. To do this we call __dyld_fork_child in the dyanmic -// linker. But since we can't dynamically bind anything until this is done we -// do this by using the private extern __dyld_func_lookup() function to get the -// address of __dyld_fork_child (the 'C' code equivlent): -// -// _dyld_func_lookup("__dyld_fork_child", &address); -// address(); -// -.cstring -LC0: - .ascii "__dyld_fork_child\0" - -.text - leaq 8(%rsp),%rsi // get the address where we're going to store the pointer - leaq LC0(%rip), %rdi // copy the name of the function to look up - call __dyld_func_lookup - call *8(%rsp) // call __dyld_fork_child indirectly -#endif xorq %rax, %rax - REG_TO_EXTERN(%rax, __current_pid) - CALL_EXTERN(__cthread_fork_child) - - xorq %rax,%rax // zero rax - addq $24, %rsp // restore the stack - ret - - //parent here... + PICIFY(__current_pid) + movl %eax,(%r11) L2: - movl %eax, 16(%rsp) // save pid - - CALL_EXTERN_AGAIN(__cthread_fork_parent) - movl 16(%rsp), %eax // return pid + // parent ends up here skipping child portion addq $24, %rsp // restore the stack - ret - -#elif defined(__arm__) - - .globl cerror - MI_ENTRY_POINT(_fork) - stmfd sp!, {r4, r7, lr} - add r7, sp, #4 - MI_CALL_EXTERNAL(__cthread_fork_prepare) - mov r1, #1 // prime results - mov r12, #SYS_fork - swi #SWI_SYSCALL // make the syscall - bcs Lbotch // error? - cmp r1, #0 // parent (r1=0) or child(r1=1) - beq Lparent - - //child here... - MI_GET_ADDRESS(r3, __current_pid) - mov r0, #0 - str r0, [r3] // clear cached pid in child - -#if defined(__DYNAMIC__) -// Here on the child side of the fork we need to tell the dynamic linker that -// we have forked. To do this we call __dyld_fork_child in the dyanmic -// linker. But since we can't dynamicly bind anything until this is done we -// do this by using the private extern __dyld_func_lookup() function to get the -// address of __dyld_fork_child (the 'C' code equivlent): -// -// _dyld_func_lookup("__dyld_fork_child", &address); -// address(); -// - .cstring - .align 2 -LC0: - .ascii "__dyld_fork_child\0" -.text -.align 2 - sub sp, sp, #4 // allocate space for the address parameter - mov r1, sp // get the address of the allocated space - ldr r0, LP0 // get the name of the function to look up -L0: add r0, pc, r0 - bl __dyld_func_lookup - mov lr, pc - ldr pc, [sp], #4 // call __dyld_fork_child indirectly and pop -#endif - MI_CALL_EXTERNAL(__cthread_fork_child) // let child get ready - mov r0, #0 - ldmfd sp!, {r4, r7, pc} - -Lbotch: - MI_CALL_EXTERNAL(cerror) // jump here on error - mov r0,#-1 // set the error - // fall thru - -Lparent: - mov r4, r0 // save child pid - MI_CALL_EXTERNAL(__cthread_fork_parent) - mov r0, r4 // restore child pid - ldmfd sp!, {r4, r7, pc} // pop and return - - .align 2 -#if defined(__DYNAMIC__) -LP0: - .long LC0-(L0+8) -#endif + ret #else #error Unsupported architecture