NaCl: Set tid field to a unique value.

This commit is contained in:
Roland McGrath 2015-05-20 14:52:05 -07:00
parent 5e2aa9a421
commit 7cea621278
6 changed files with 139 additions and 4 deletions

View File

@ -1,5 +1,15 @@
2015-05-20 Roland McGrath <roland@hack.frob.com>
* sysdeps/nacl/pthread-pids.h: New file.
* sysdeps/nacl/createthread.c: Include <pthread-pids.h>.
(create_thread): Use __nacl_get_tid to initialize PD->tid.
* nptl/pthread-pids.h: New file.
* sysdeps/unix/sysv/linux/pthread-pids.h: New file.
* nptl/nptl-init.c: Include <pthread-pids.h>.
(__pthread_initialize_minimal_internal):
Call __pthread_initialize_pids instead of set_tid_address syscall.
* sysdeps/unix/sysv/linux/usleep.c: Moved to ...
* sysdeps/posix/usleep.c: ... here.

View File

@ -36,6 +36,7 @@
#include <lowlevellock.h>
#include <kernel-features.h>
#include <libc-internal.h>
#include <pthread-pids.h>
#ifndef TLS_MULTIPLE_THREADS_IN_TCB
/* Pointer to the corresponding variable in libc. */
@ -311,10 +312,7 @@ __pthread_initialize_minimal_internal (void)
/* Minimal initialization of the thread descriptor. */
struct pthread *pd = THREAD_SELF;
#ifdef __NR_set_tid_address
INTERNAL_SYSCALL_DECL (err);
pd->pid = pd->tid = INTERNAL_SYSCALL (set_tid_address, err, 1, &pd->tid);
#endif
__pthread_initialize_pids (pd);
THREAD_SETMEM (pd, specific[0], &pd->specific_1stblock[0]);
THREAD_SETMEM (pd, user_stack, true);
if (LLL_LOCK_INITIALIZER != 0)

29
nptl/pthread-pids.h Normal file
View File

@ -0,0 +1,29 @@
/* Initialize pid and tid fields of struct pthread. Stub version.
Copyright (C) 2015 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 <pthreadP.h>
/* Initialize PD->pid and PD->tid for the initial thread. If there is
setup required to arrange that __exit_thread causes PD->tid to be
cleared and futex-woken, then this function should do that as well. */
static inline void
__pthread_initialize_pids (struct pthread *pd)
{
#error "sysdeps pthread-pids.h file required"
pd->pid = pd->tid = -1;
}

View File

@ -17,6 +17,7 @@
<http://www.gnu.org/licenses/>. */
#include <nacl-interfaces.h>
#include <pthread-pids.h>
/* See the comments in pthread_create.c for the requirements for these
two macros and the create_thread function. */
@ -33,6 +34,8 @@ static int
create_thread (struct pthread *pd, const struct pthread_attr *attr,
bool stopped_start, STACK_VARIABLES_PARMS, bool *thread_ran)
{
pd->tid = __nacl_get_tid (pd);
pd->stopped_start = stopped_start;
if (__glibc_unlikely (stopped_start))
/* We make sure the thread does not run far by forcing it to get a

View File

@ -0,0 +1,65 @@
/* Initialize pid and tid fields of struct pthread. NaCl version.
Copyright (C) 2015 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 <pthreadP.h>
/* NaCl has no concept of PID or TID, nor even any notion of an
identifier for a thread within the process. But various places in
the NPTL implementation rely on using the 'tid' field of the TCB
(struct pthread) as an identifier that is unique at least among all
live threads in the process. So we must synthesize some number to
use. Conveniently, the 'pthread_t' value itself is already unique
in exactly this way (because it's the 'struct pthread' pointer).
The only wrinkle is that 'tid' is a (32-bit) 'int' and its high
(sign) bit is used for special purposes, so we must be absolutely
sure that we never use a pointer value with the high bit set. (It
also cannot be zero, but zero is never a valid pointer anyway.)
The NaCl sandbox models for 32-bit machines limit the address space
to less than 3GB (in fact, to 1GB), so it's already impossible that
a valid pointer will have its high bit set. But the NaCl x86-64
sandbox model allows a full 4GB of address space, so we cannot
assume that an arbitrary pointer value will not have the high bit
set. Conveniently, there are always unused bits in the pointer
value for a 'struct pthread', because it is always aligned to at
least 32 bits and so the low bits are always zero. Hence, we can
safely avoid the danger of a nonzero high bit just by shifting the
pointer value right. */
static inline int
__nacl_get_tid (struct pthread *pd)
{
uintptr_t id = (uintptr_t) pd;
int tid = id >> 1;
assert ((id & 1) == 0);
assert (sizeof id == sizeof tid);
assert (tid > 0);
return tid;
}
/* Initialize PD->pid and PD->tid for the initial thread. If there is
setup required to arrange that __exit_thread causes PD->tid to be
cleared and futex-woken, then this function should do that as well. */
static inline void
__pthread_initialize_pids (struct pthread *pd)
{
pd->tid = __nacl_get_tid (pd);
pd->pid = -1;
}

View File

@ -0,0 +1,30 @@
/* Initialize pid and tid fields of struct pthread. Linux version.
Copyright (C) 2015 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 <pthreadP.h>
#include <sysdep.h>
/* Initialize PD->pid and PD->tid for the initial thread. If there is
setup required to arrange that __exit_thread causes PD->tid to be
cleared and futex-woken, then this function should do that as well. */
static inline void
__pthread_initialize_pids (struct pthread *pd)
{
INTERNAL_SYSCALL_DECL (err);
pd->pid = pd->tid = INTERNAL_SYSCALL (set_tid_address, err, 1, &pd->tid);
}