1 | /* Wrapper around clone system call. 64 bit S/390 version. |
2 | Copyright (C) 2001-2024 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. |
4 | |
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. |
9 | |
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. |
14 | |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; if not, see |
17 | <https://www.gnu.org/licenses/>. */ |
18 | |
19 | /* clone is even more special than fork as it mucks with stacks |
20 | and invokes a function in the right context after its all over. */ |
21 | |
22 | #include <sysdep.h> |
23 | #include <tls.h> |
24 | #define _ERRNO_H 1 |
25 | #include <bits/errno.h> |
26 | |
27 | /* int __clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, |
28 | pid_t *parent_tid, void *tls, pid_t *child_tid); */ |
29 | /* sys_clone (void *child_stack, unsigned long flags, |
30 | pid_t *parent_tid, pid_t *child_tid, void *tls); */ |
31 | |
32 | .text |
33 | ENTRY(__clone) |
34 | stmg %r6,%r7,48(%r15) /* Save registers. */ |
35 | cfi_offset (%r7,-104) |
36 | cfi_offset (%r6,-112) |
37 | ltgr %r7,%r2 /* check fn and move to %r7 */ |
38 | jz error /* no NULL function pointers */ |
39 | lghi %r0,-16 /* Align the child_stack to a ... */ |
40 | ngr %r3,%r0 /* double word boundary and ... */ |
41 | jz error /* avoid NULL stack pointers. */ |
42 | lgr %r0,%r5 /* move *arg out of the way */ |
43 | lgr %r2,%r3 /* move child_stack to %r2 */ |
44 | lgr %r3,%r4 /* move flags to %r3 */ |
45 | lgr %r4,%r6 /* move parent_tid to %r4 */ |
46 | lg %r5,168(%r15) /* load child_tid from stack */ |
47 | lg %r6,160(%r15) /* load tls from stack */ |
48 | lghi %r1,SYS_ify (clone) |
49 | svc 0 |
50 | ltgr %r2,%r2 /* check return code */ |
51 | jz thread_start |
52 | lmg %r6,%r7,48(%r15) /* Restore registers. */ |
53 | jgm SYSCALL_ERROR_LABEL |
54 | br %r14 |
55 | error: |
56 | lghi %r2,-EINVAL |
57 | lmg %r6,%r7,48(%r15) /* Restore registers. */ |
58 | jg SYSCALL_ERROR_LABEL |
59 | PSEUDO_END (__clone) |
60 | |
61 | thread_start: |
62 | cfi_startproc |
63 | /* Mark r14 as undefined in order to stop unwinding here! */ |
64 | cfi_undefined (r14) |
65 | /* fn is in gpr 7, arg in gpr 0 */ |
66 | lgr %r2,%r0 /* set first parameter to void *arg */ |
67 | aghi %r15,-160 /* make room on the stack for the save area */ |
68 | xc 0(8,%r15),0(%r15) |
69 | basr %r14,%r7 /* jump to fn */ |
70 | DO_CALL (exit, 1) |
71 | cfi_endproc |
72 | |
73 | libc_hidden_def (__clone) |
74 | weak_alias (__clone, clone) |
75 | |