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:
Richard Henderson 2014-05-23 16:23:32 -04:00
parent 111cc71489
commit 89b4bd6b60
4 changed files with 82 additions and 45 deletions

View File

@ -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.

View 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"

View File

@ -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

View File

@ -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)