Start cleaning up TLS initial value for pthread_create.

This commit is contained in:
Roland McGrath 2014-06-09 12:52:55 -07:00
parent 2976feab1f
commit 962b744d06
5 changed files with 58 additions and 70 deletions

View File

@ -1,3 +1,14 @@
2014-06-09 Roland McGrath <roland@hack.frob.com>
* nptl/sysdeps/pthread/createthread.c (TLS_DEFINE_INIT_TP): New macro,
if not already defined.
(do_clone): Use that in place of PREPARE_CREATE and TLS_VALUE.
* nptl/sysdeps/x86_64/tls.h (TLS_DEFINE_INIT_TP): New macro.
* nptl/sysdeps/i386/tls.h (tls_fill_user_desc): New function.
(TLS_INIT_TP): Use it.
(TLS_DEFINE_INIT_TP): New macro.
* sysdeps/unix/sysv/linux/i386/createthread.c: File removed.
2014-06-09 Joseph Myers <joseph@codesourcery.com> 2014-06-09 Joseph Myers <joseph@codesourcery.com>
* conform/data/termios.h-data [POSIX] (IUCLC): Do not expect * conform/data/termios.h-data [POSIX] (IUCLC): Do not expect

View File

@ -192,6 +192,26 @@ union user_desc_init
# endif # endif
#endif #endif
static inline void __attribute__ ((unused, always_inline))
tls_fill_user_desc (union user_desc_init *desc,
unsigned int entry_number,
void *pd)
{
desc->vals[0] = entry_number;
/* The 'base_addr' field. Pointer to the TCB. */
desc->vals[1] = (unsigned long int) pd;
/* The 'limit' field. We use 4GB which is 0xfffff pages. */
desc->vals[2] = 0xfffff;
/* Collapsed value of the bitfield:
.seg_32bit = 1
.contents = 0
.read_exec_only = 0
.limit_in_pages = 1
.seg_not_present = 0
.useable = 1 */
desc->vals[3] = 0x51;
}
/* Code to initially initialize the thread pointer. This might need /* Code to initially initialize the thread pointer. This might need
special attention since 'errno' is not yet available and if the special attention since 'errno' is not yet available and if the
operation can cause a failure 'errno' must not be touched. */ operation can cause a failure 'errno' must not be touched. */
@ -207,20 +227,8 @@ union user_desc_init
/* New syscall handling support. */ \ /* New syscall handling support. */ \
INIT_SYSINFO; \ INIT_SYSINFO; \
\ \
/* The 'entry_number' field. Let the kernel pick a value. */ \ /* Let the kernel pick a value for the 'entry_number' field. */ \
_segdescr.vals[0] = -1; \ tls_fill_user_desc (&_segdescr, -1, _thrdescr); \
/* The 'base_addr' field. Pointer to the TCB. */ \
_segdescr.vals[1] = (unsigned long int) _thrdescr; \
/* The 'limit' field. We use 4GB which is 0xfffff pages. */ \
_segdescr.vals[2] = 0xfffff; \
/* Collapsed value of the bitfield: \
.seg_32bit = 1 \
.contents = 0 \
.read_exec_only = 0 \
.limit_in_pages = 1 \
.seg_not_present = 0 \
.useable = 1 */ \
_segdescr.vals[3] = 0x51; \
\ \
/* Install the TLS. */ \ /* Install the TLS. */ \
asm volatile (TLS_LOAD_EBX \ asm volatile (TLS_LOAD_EBX \
@ -244,6 +252,15 @@ union user_desc_init
_result == 0 ? NULL \ _result == 0 ? NULL \
: "set_thread_area failed when setting up thread-local storage\n"; }) : "set_thread_area failed when setting up thread-local storage\n"; })
# define TLS_DEFINE_INIT_TP(tp, pd) \
union user_desc_init _segdescr; \
/* Find the 'entry_number' field that the kernel selected in TLS_INIT_TP. \
The first three bits of the segment register value select the GDT, \
ignore them. We get the index from the value of the %gs register in \
the current thread. */ \
tls_fill_user_desc (&_segdescr, TLS_GET_GS () >> 3, pd); \
const struct user_desc *tp = &_segdescr.desc
/* Return the address of the dtv for the current thread. */ /* Return the address of the dtv for the current thread. */
# define THREAD_DTV() \ # define THREAD_DTV() \

View File

@ -30,10 +30,18 @@
#define CLONE_SIGNAL (CLONE_SIGHAND | CLONE_THREAD) #define CLONE_SIGNAL (CLONE_SIGHAND | CLONE_THREAD)
/* Unless otherwise specified, the thread "register" is going to be /* The <tls.h> header should define the macro TLS_DEFINE_INIT_TP such that:
initialized with a pointer to the TCB. */ TLS_DEFINE_INIT_TP (VAR, PD);
#ifndef TLS_VALUE Declares and initializes a variable VAR with the value that should
# define TLS_VALUE pd be passed to the OS thread creation function (e.g. clone) to initialize
its TLS state for the 'struct pthread *' PD. */
#ifndef TLS_DEFINE_INIT_TP
/* For a transitional period while all the <tls.h> implementations are
getting updated, we define it using the old TLS_VALUE macro. */
# define TLS_DEFINE_INIT_TP(tp, pd) void *tp = TLS_VALUE
# ifndef TLS_VALUE
# define TLS_VALUE pd
# endif
#endif #endif
#ifndef ARCH_CLONE #ifndef ARCH_CLONE
@ -52,9 +60,7 @@ do_clone (struct pthread *pd, const struct pthread_attr *attr,
int clone_flags, int (*fct) (void *), STACK_VARIABLES_PARMS, int clone_flags, int (*fct) (void *), STACK_VARIABLES_PARMS,
int stopped) int stopped)
{ {
#ifdef PREPARE_CREATE TLS_DEFINE_INIT_TP (tp, pd);
PREPARE_CREATE;
#endif
if (__glibc_unlikely (stopped != 0)) if (__glibc_unlikely (stopped != 0))
/* We make sure the thread does not run far by forcing it to get a /* We make sure the thread does not run far by forcing it to get a
@ -73,7 +79,7 @@ do_clone (struct pthread *pd, const struct pthread_attr *attr,
atomic_increment (&__nptl_nthreads); atomic_increment (&__nptl_nthreads);
int rc = ARCH_CLONE (fct, STACK_VARIABLES_ARGS, clone_flags, int rc = ARCH_CLONE (fct, STACK_VARIABLES_ARGS, clone_flags,
pd, &pd->tid, TLS_VALUE, &pd->tid); pd, &pd->tid, tp, &pd->tid);
if (__glibc_unlikely (rc == -1)) if (__glibc_unlikely (rc == -1))
{ {

View File

@ -164,6 +164,8 @@ typedef struct
_result ? "cannot set %fs base address for thread-local storage" : 0; \ _result ? "cannot set %fs base address for thread-local storage" : 0; \
}) })
# define TLS_DEFINE_INIT_TP(tp, pd) void *tp = (pd)
/* Return the address of the dtv for the current thread. */ /* Return the address of the dtv for the current thread. */
# define THREAD_DTV() \ # define THREAD_DTV() \

View File

@ -1,48 +0,0 @@
/* Copyright (C) 2002-2014 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
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/>. */
/* The "thread register" gets initialized from a segment descriptor.
Initialize such a descriptor first. */
#define PREPARE_CREATE \
union user_desc_init desc; \
\
/* Describe the thread-local storage segment. */ \
\
/* The 'entry_number' field. The first three bits of the segment \
register value select the GDT, ignore them. We get the index \
from the value of the %gs register in the current thread. */ \
desc.vals[0] = TLS_GET_GS () >> 3; \
/* The 'base_addr' field. Pointer to the TCB. */ \
desc.vals[1] = (unsigned long int) pd; \
/* The 'limit' field. We use 4GB which is 0xfffff pages. */ \
desc.vals[2] = 0xfffff; \
/* Collapsed value of the bitfield: \
.seg_32bit = 1 \
.contents = 0 \
.read_exec_only = 0 \
.limit_in_pages = 1 \
.seg_not_present = 0 \
.useable = 1 */ \
desc.vals[3] = 0x51
/* Value passed to 'clone' for initialization of the thread register. */
#define TLS_VALUE &desc.desc
/* Get the real implementation. */
#include <nptl/sysdeps/pthread/createthread.c>