/*
- * Copyright (c) 1999-2007 Apple Inc. All rights reserved.
+ * Copyright (c) 1999-2010 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* 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 <architecture/ppc/mode_independent_asm.h>
-
-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
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
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