]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
ARC: Add the clone3 wrapper
authorPavel Kozlov <pavel.kozlov@synopsys.com>
Thu, 2 Mar 2023 16:10:18 +0000 (20:10 +0400)
committerPavel Kozlov <pavel.kozlov@synopsys.com>
Mon, 13 Mar 2023 14:12:32 +0000 (18:12 +0400)
Use the clone3 wrapper on ARC. It doesn't care about stack alignment.
All callers should provide an aligned stack.
It follows the internal signature:

extern int clone3 (struct clone_args *__cl_args, size_t __size,
 int (*__func) (void *__arg), void *__arg);

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
sysdeps/unix/sysv/linux/arc/clone3.S [new file with mode: 0644]
sysdeps/unix/sysv/linux/arc/sysdep.h

diff --git a/sysdeps/unix/sysv/linux/arc/clone3.S b/sysdeps/unix/sysv/linux/arc/clone3.S
new file mode 100644 (file)
index 0000000..87a8272
--- /dev/null
@@ -0,0 +1,90 @@
+/* The clone3 syscall wrapper.  Linux/arc version.
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <sysdep.h>
+#define _ERRNO_H       1
+#include <bits/errno.h>
+
+/* The userland implementation is:
+   int clone3 (struct clone_args *cl_args, size_t size,
+               int (*func)(void *arg), void *arg);
+
+   the kernel entry is:
+   int clone3 (struct clone_args *cl_args, size_t size);
+
+   The parameters are passed in registers from userland:
+   r0: cl_args
+   r1: size
+   r2: func
+   r3: arg  */
+
+ENTRY(__clone3)
+
+       /* Save args for the child.  */
+       mov     r10, r0         /* cl_args  */
+       mov     r11, r2         /* func  */
+       mov     r12, r3         /* args  */
+
+       /* Sanity check args.  */
+       breq    r10, 0, L (__sys_err)   /* No NULL cl_args pointer.  */
+       breq    r11, 0, L (__sys_err)   /* No NULL function pointer.  */
+
+       /* Do the system call, the kernel expects:
+          r8: system call number
+          r0: cl_args
+          r1: size  */
+       mov     r0, r10
+       mov     r8, __NR_clone3
+       ARC_TRAP_INSN
+
+       cmp     r0, 0
+       beq     thread_start_clone3     /* Child returns.  */
+       blt     L (__sys_err2)
+       j       [blink]                 /* Parent returns.  */
+
+L (__sys_err):
+       mov     r0, -EINVAL
+L (__sys_err2):
+       b       __syscall_error
+PSEUDO_END (__clone3)
+
+
+       .align 4
+       .type thread_start_clone3, %function
+thread_start_clone3:
+       cfi_startproc
+       /* Terminate call stack by noting ra is undefined.  */
+       cfi_undefined (blink)
+
+       /* Child jumps off to @fn with @arg as argument.  */
+       jl.d    [r11]
+       mov     r0, r12
+
+       /* exit() with result from @fn (already in r0).  */
+       mov     r8, __NR_exit
+       ARC_TRAP_INSN
+
+       /* In case it ever came back.  */
+       flag    1
+
+       cfi_endproc
+       .size thread_start_clone3, .-thread_start_clone3
+
+libc_hidden_def (__clone3)
+weak_alias (__clone3, clone3)
index dd6fe73445f9f16b74a1dc3f4adb8fc5a91f7510..88dc1dff017f550966d035821dc669d2cedd9a2c 100644 (file)
@@ -141,6 +141,8 @@ hidden_proto (__syscall_error)
 
 # define ARC_TRAP_INSN "trap_s 0       \n\t"
 
+# define HAVE_CLONE3_WRAPPER   1
+
 # undef INTERNAL_SYSCALL_NCS
 # define INTERNAL_SYSCALL_NCS(number, nr_args, args...)        \
   ({                                                           \