aarch64: Consolidate NPTL/non versions of vfork
At the same time, incorporate the 0 -> 0x80000000 mapping of the pid expected by raise.c.
This commit is contained in:
parent
111cc71489
commit
89b4bd6b60
|
@ -1,5 +1,12 @@
|
|||
2014-06-03 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* sysdeps/unix/sysv/linux/aarch64/pt-vfork.c: New file.
|
||||
* sysdeps/unix/sysv/linux/aarch64/nptl/pt-vfork.S: Remove file.
|
||||
* sysdeps/unix/sysv/linux/aarch64/vfork.S (__vfork): Incorporate
|
||||
SAVE_PID and RESTORE_PID blocks from pt-vfork.S. Map 0 to INT_MIN
|
||||
in the SAVE_PID block.
|
||||
(__libc_vfork): New alias.
|
||||
|
||||
* sysdeps/unix/sysv/linux/aarch64/clone.S (__clone): Save args for
|
||||
child in registers, not on the stack. Remove RESET_PID conditionals.
|
||||
* sysdeps/unix/sysv/linux/aarch64/nptl/clone.S: Remove file.
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
/* Copyright (C) 2009-2014 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
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <tcb-offsets.h>
|
||||
|
||||
/* Save the PID value. */
|
||||
#define SAVE_PID \
|
||||
mrs x2, tpidr_el0; \
|
||||
sub x2, x2, #PTHREAD_SIZEOF; \
|
||||
ldr w3, [x2, #PTHREAD_PID_OFFSET]; \
|
||||
neg w0, w3; \
|
||||
str w0, [x2, #PTHREAD_PID_OFFSET]
|
||||
|
||||
/* Restore the old PID value in the parent. */
|
||||
#define RESTORE_PID \
|
||||
cbz x0, 1f; \
|
||||
str w3, [x2, #PTHREAD_PID_OFFSET]; \
|
||||
1:
|
||||
|
||||
#include "../vfork.S"
|
|
@ -0,0 +1,54 @@
|
|||
/* vfork ABI-compatibility entry points for libpthread.
|
||||
Copyright (C) 2014 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
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <shlib-compat.h>
|
||||
|
||||
/* libpthread used to have its own vfork implementation that differed
|
||||
from libc's only in having a pointless micro-optimization. There
|
||||
is no longer any use to having a separate copy in libpthread, but
|
||||
the historical ABI requires it. For static linking, there is no
|
||||
need to provide anything here--the libc version will be linked in.
|
||||
For shared library ABI compatibility, there must be __vfork and
|
||||
vfork symbols in libpthread.so. */
|
||||
|
||||
#if HAVE_IFUNC
|
||||
# include <nptl/pt-vfork.c>
|
||||
#elif (SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_20) \
|
||||
|| SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_20))
|
||||
|
||||
/* Thankfully, on AArch64 we can rely on the compiler generating
|
||||
a tail call here. */
|
||||
|
||||
extern void __libc_vfork (void);
|
||||
|
||||
void
|
||||
vfork_compat (void)
|
||||
{
|
||||
__libc_vfork ();
|
||||
}
|
||||
|
||||
# if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_20)
|
||||
compat_symbol (libpthread, vfork_compat, vfork, GLIBC_2_0);
|
||||
# endif
|
||||
|
||||
# if SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_20)
|
||||
strong_alias (vfork_compat, vfork_compat2)
|
||||
compat_symbol (libpthread, vfork_compat2, __vfork, GLIBC_2_1_2);
|
||||
# endif
|
||||
|
||||
#endif
|
|
@ -28,22 +28,33 @@
|
|||
|
||||
ENTRY (__vfork)
|
||||
|
||||
#ifdef SAVE_PID
|
||||
SAVE_PID
|
||||
#endif
|
||||
/* Save the TCB-cached PID away in w3, and then negate the TCB
|
||||
field. But if it's zero, set it to 0x80000000 instead. See
|
||||
raise.c for the logic that relies on this value. */
|
||||
mrs x2, tpidr_el0
|
||||
sub x2, x2, #PTHREAD_SIZEOF
|
||||
ldr w3, [x2, #PTHREAD_PID_OFFSET]
|
||||
mov w1, #0x80000000
|
||||
negs w0, w3
|
||||
csel w0, w1, w0, eq
|
||||
str w0, [x2, #PTHREAD_PID_OFFSET]
|
||||
|
||||
mov x0, #0x4111 /* CLONE_VM | CLONE_VFORK | SIGCHLD */
|
||||
mov x1, sp
|
||||
DO_CALL (clone, 2)
|
||||
#ifdef RESTORE_PID
|
||||
RESTORE_PID
|
||||
#endif
|
||||
cmn x0, #4095
|
||||
b.cs 1f
|
||||
RET
|
||||
|
||||
/* Restore the original value of the TCB cache of the PID, if we're
|
||||
the parent. But in the child (syscall return value equals zero),
|
||||
leave things as they are. */
|
||||
cbz x0, 1f
|
||||
str w3, [x2, #PTHREAD_PID_OFFSET]
|
||||
1:
|
||||
b SYSCALL_ERROR
|
||||
cmn x0, #4095
|
||||
b.cs .Lsyscall_error
|
||||
RET
|
||||
|
||||
PSEUDO_END (__vfork)
|
||||
libc_hidden_def (__vfork)
|
||||
|
||||
weak_alias (__vfork, vfork)
|
||||
strong_alias (__vfork, __libc_vfork)
|
||||
|
|
Loading…
Reference in New Issue