1 /* Copyright (C) 2002 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Bruno Haible <bruno@clisp.org>, 2002.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 /* __start_thread (flags, stack, func, arg)
21 calls __rfork (flags), and in the child sets the stack pointer and then
22 calls _exit (func (arg)).
23 It cannot be done in portable C. */
26 #include <asm-syntax.h>
30 ENTRY (__start_thread)
31 /* End FDE now, because in the child the unwind info will be
35 /* There is a window of a few instructions, right after the rfork
36 system call, where the handling of a signal would write garbage
37 into the stack shared by the parent and the child (assuming
38 RFMEM is set in flags). To solve this: 1. We block all signals
39 around the rfork system call and unblock them afterwards in
40 the parent and in the child (but only after changing the stack
41 pointer). 2. The child accesses only values passed in registers
42 and on its own stack. This way, if the parent is scheduled to
43 run first, and handles a signal, it will not affect the child;
44 and if the child runs first, and handles a signal, it will use
45 the child's stack and not affect the parent.
46 We need to pass 7 words of info to the child: stack, func, arg,
47 and the signal mask to restore. Since we have only 4 call-saved
48 registers available (%ebx, %esi, %edi, %ebp), we pass only the
49 stack pointer in a register, and the rest through the child's
56 movl 8(%ebp), %eax /* flags */
57 testl $32, %eax /* flags & RFMEM */
60 /* Block all signals. */
67 movl $SIG_SETMASK, 4(%esp)
70 DO_CALL (sigprocmask, 3)
73 /* Copy all info to the child's stack. */
74 movl 12(%ebp), %ebx /* stack */
75 subl $32, %ebx /* room for func, arg, sigset_t */
76 andl $-16, %ebx /* make it 16-bytes aligned */
77 movl 16(%ebp), %eax /* func */
78 movl 20(%ebp), %edx /* arg */
81 movl 16(%esp), %eax /* sigset_t word 0 */
82 movl 20(%esp), %edx /* sigset_t word 1 */
85 movl 24(%esp), %eax /* sigset_t word 2 */
86 movl 28(%esp), %edx /* sigset_t word 3 */
90 /* Perform the rfork system call. */
91 movl 8(%ebp), %eax /* flags */
96 /* %edx is now 0 for the parent and 1 for the child. */
100 /* Save the child pid, currently in %eax. */
103 /* Restore the previous signal mask. */
105 movl $SIG_SETMASK, 4(%esp)
108 DO_CALL (sigprocmask, 3)
110 /* Return the child pid, currently in %ebx. */
117 L(child):/* Here we are in the child thread. */
119 /* Set the stack pointer. */
121 /* Terminate the stack frame. */
126 /* Restore the previous signal mask. */
128 movl $SIG_SETMASK, 4(%esp)
131 DO_CALL (sigprocmask, 3)
134 /* Call func (arg). */
142 addl $_GLOBAL_OFFSET_TABLE_+[.-L(here)], %ebx
145 call HIDDEN_JUMPTARGET (_exit)
147 L(simple):/* Simple case without signal mask handling. */
149 /* Copy all info to the child's stack. */
150 movl 12(%ebp), %ebx /* stack */
151 subl $8, %ebx /* room for func, arg */
152 andl $-16, %ebx /* make it 16-bytes aligned */
153 movl 16(%ebp), %eax /* func */
154 movl 20(%ebp), %edx /* arg */
158 /* Perform the rfork system call. */
159 movl 8(%ebp), %eax /* flags */
164 /* %edx is now 0 for the parent and 1 for the child. */
168 /* Return the child pid, currently in %eax. */
175 L(simple_child):/* Here we are in the child thread. */
177 /* Set the stack pointer. */
179 /* Terminate the stack frame. */
188 /* Save the error code, currently in %eax. */
191 /* Restore the previous signal mask. */
193 movl $SIG_SETMASK, 4(%esp)
196 DO_CALL (sigprocmask, 3)
198 /* load saved error code */
205 jmp SYSCALL_ERROR_LABEL
207 PSEUDO_END (__start_thread)