]>
Commit | Line | Data |
---|---|---|
568035b7 | 1 | /* Copyright (C) 2005-2013 Free Software Foundation, Inc. |
da1ea0f0 CD |
2 | This file is part of the GNU C Library. |
3 | ||
4 | The GNU C Library is free software; you can redistribute it and/or | |
5 | modify it under the terms of the GNU Lesser General Public | |
6 | License as published by the Free Software Foundation; either | |
7 | version 2.1 of the License, or (at your option) any later version. | |
8 | ||
9 | The GNU C Library is distributed in the hope that it will be useful, | |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 | Lesser General Public License for more details. | |
13 | ||
14 | You should have received a copy of the GNU Lesser General Public | |
ab84e3ff PE |
15 | License along with the GNU C Library. If not, see |
16 | <http://www.gnu.org/licenses/>. */ | |
da1ea0f0 CD |
17 | |
18 | #include <sysdep.h> | |
19 | #define _ERRNO_H 1 | |
20 | #include <bits/errno.h> | |
21 | #include <tcb-offsets.h> | |
22 | ||
23 | /* Clone the calling process, but without copying the whole address space. | |
24 | The calling process is suspended until the new process exits or is | |
25 | replaced by a call to `execve'. Return -1 for errors, 0 to the new process, | |
26 | and the process ID of the new process to the old process. */ | |
27 | ||
28 | /* Load the thread register. | |
29 | Load the saved PID value. | |
30 | Negate the value. | |
31 | Store the temporary PID. */ | |
32 | #define SAVE_PID \ | |
33 | mfctl %cr27, %r26 ASM_LINE_SEP \ | |
34 | ldw PID_THREAD_OFFSET(%r26),%r1 ASM_LINE_SEP \ | |
35 | sub %r0,%r1,%r1 ASM_LINE_SEP \ | |
36 | stw %r1,PID_THREAD_OFFSET(%r26) ASM_LINE_SEP | |
37 | /* If we are the parent... | |
38 | Get the thread pointer. | |
39 | Load the saved PID. | |
40 | Negate the value (got back original) | |
41 | Restore the PID. */ | |
42 | #define RESTORE_PID \ | |
43 | cmpb,=,n %r0,%ret0,.Lthread_start ASM_LINE_SEP \ | |
44 | mfctl %cr27, %r26 ASM_LINE_SEP \ | |
45 | ldw PID_THREAD_OFFSET(%r26),%r1 ASM_LINE_SEP \ | |
46 | sub %r0,%r1,%r1 ASM_LINE_SEP \ | |
47 | stw %r1,PID_THREAD_OFFSET(%r26) ASM_LINE_SEP \ | |
48 | .Lthread_start: ASM_LINE_SEP | |
49 | ||
50 | /* r26, r25, r24, r23 are free since vfork has no arguments */ | |
51 | ENTRY(__vfork) | |
5556231d | 52 | /* We must not create a frame. When the child unwinds to call |
3680f14a CD |
53 | exec it will clobber the same frame that the parent |
54 | needs to unwind. */ | |
da1ea0f0 CD |
55 | |
56 | /* Save the PIC register. */ | |
57 | #ifdef PIC | |
58 | copy %r19, %r25 /* parent */ | |
59 | #endif | |
60 | ||
61 | /* Save the process PID */ | |
62 | SAVE_PID | |
63 | ||
64 | /* Syscall saves and restores all register states */ | |
65 | ble 0x100(%sr2,%r0) | |
66 | ldi __NR_vfork,%r20 | |
67 | ||
68 | /* Conditionally restore the PID */ | |
69 | RESTORE_PID | |
70 | ||
71 | /* Check for error */ | |
72 | ldi -4096,%r1 | |
73 | comclr,>>= %r1,%ret0,%r0 /* Note: unsigned compare. */ | |
74 | b,n .Lerror | |
75 | ||
3680f14a CD |
76 | /* Return, and DO NOT restore rp. The child may have called |
77 | functions that updated the frame's rp. This works because | |
5556231d | 78 | the kernel ensures rp is preserved across the vfork |
3680f14a CD |
79 | syscall. */ |
80 | bv,n %r0(%rp) | |
da1ea0f0 CD |
81 | |
82 | .Lerror: | |
3680f14a CD |
83 | /* Now we need a stack to call a function. We are assured |
84 | that there is no child now, so it's safe to create | |
85 | a frame. */ | |
86 | stw %rp, -20(%sp) | |
87 | stwm %r3, 64(%sp) | |
88 | stw %sp, -4(%sp) | |
89 | ||
0daa0500 | 90 | sub %r0,%ret0,%r3 |
da1ea0f0 CD |
91 | SYSCALL_ERROR_HANDLER |
92 | /* Restore the PIC register (in delay slot) on error */ | |
93 | #ifdef PIC | |
94 | copy %r25, %r19 /* parent */ | |
95 | #else | |
96 | nop | |
97 | #endif | |
0daa0500 CD |
98 | /* Write syscall return into errno location */ |
99 | stw %r3, 0(%ret0) | |
100 | ldw -84(%sp), %rp | |
101 | bv %r0(%rp) | |
102 | ldwm -64(%sp), %r3 | |
da1ea0f0 CD |
103 | PSEUDO_END (__vfork) |
104 | libc_hidden_def (__vfork) | |
105 | weak_alias (__vfork, vfork) | |
106 |