elf: Introduce __tls_init_tp for second-phase TCB initialization

TLS_INIT_TP is processor-specific, so it is not a good place to
put thread library initialization code (it would have to be repeated
for all CPUs).  Introduce __tls_init_tp as a separate function,
to be called immediately after TLS_INIT_TP.  Move the existing
stack list setup code for NPTL to this function.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
This commit is contained in:
Florian Weimer 2021-04-21 19:49:51 +02:00
parent 90e97b3720
commit 90d7e7e5bd
6 changed files with 63 additions and 20 deletions

View File

@ -24,7 +24,6 @@
#include <stdio.h> #include <stdio.h>
#include <sys/param.h> #include <sys/param.h>
#include <array_length.h> #include <array_length.h>
#include <list.h>
#ifdef SHARED #ifdef SHARED
#error makefile bug, this file is for static only #error makefile bug, this file is for static only
@ -193,12 +192,7 @@ __libc_setup_tls (void)
#endif #endif
if (__builtin_expect (lossage != NULL, 0)) if (__builtin_expect (lossage != NULL, 0))
_startup_fatal (lossage); _startup_fatal (lossage);
__tls_init_tp ();
#if THREAD_GSCOPE_IN_TCB
INIT_LIST_HEAD (&_dl_stack_used);
INIT_LIST_HEAD (&_dl_stack_user);
list_add (&THREAD_SELF->list, &_dl_stack_user);
#endif
/* Update the executable's link map with enough information to make /* Update the executable's link map with enough information to make
the TLS routines happy. */ the TLS routines happy. */

View File

@ -35,7 +35,7 @@ dl-routines = $(addprefix dl-,load lookup object reloc deps \
execstack open close trampoline \ execstack open close trampoline \
exception sort-maps lookup-direct \ exception sort-maps lookup-direct \
call-libc-early-init write \ call-libc-early-init write \
thread_gscope_wait) thread_gscope_wait tls_init_tp)
ifeq (yes,$(use-ldconfig)) ifeq (yes,$(use-ldconfig))
dl-routines += dl-cache dl-routines += dl-cache
endif endif

24
elf/dl-tls_init_tp.c Normal file
View File

@ -0,0 +1,24 @@
/* Completion of TCB initialization after TLS_INIT_TP. Generic version.
Copyright (C) 2021 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 <ldsodefs.h>
void
__tls_init_tp (void)
{
}

View File

@ -48,7 +48,6 @@
#include <array_length.h> #include <array_length.h>
#include <libc-early-init.h> #include <libc-early-init.h>
#include <dl-main.h> #include <dl-main.h>
#include <list.h>
#include <gnu/lib-names.h> #include <gnu/lib-names.h>
#include <dl-tunables.h> #include <dl-tunables.h>
@ -807,9 +806,7 @@ cannot allocate TLS data structures for initial thread\n");
const char *lossage = TLS_INIT_TP (tcbp); const char *lossage = TLS_INIT_TP (tcbp);
if (__glibc_unlikely (lossage != NULL)) if (__glibc_unlikely (lossage != NULL))
_dl_fatal_printf ("cannot set up thread-local storage: %s\n", lossage); _dl_fatal_printf ("cannot set up thread-local storage: %s\n", lossage);
#if THREAD_GSCOPE_IN_TCB __tls_init_tp ();
list_add (&THREAD_SELF->list, &GL (dl_stack_user));
#endif
tls_init_tp_called = true; tls_init_tp_called = true;
return tcbp; return tcbp;
@ -1150,11 +1147,6 @@ dl_main (const ElfW(Phdr) *phdr,
GL(dl_rtld_unlock_recursive) = rtld_lock_default_unlock_recursive; GL(dl_rtld_unlock_recursive) = rtld_lock_default_unlock_recursive;
#endif #endif
#if THREAD_GSCOPE_IN_TCB
INIT_LIST_HEAD (&GL (dl_stack_used));
INIT_LIST_HEAD (&GL (dl_stack_user));
#endif
/* The explicit initialization here is cheaper than processing the reloc /* The explicit initialization here is cheaper than processing the reloc
in the _rtld_local definition's initializer. */ in the _rtld_local definition's initializer. */
GL(dl_make_stack_executable_hook) = &_dl_make_stack_executable; GL(dl_make_stack_executable_hook) = &_dl_make_stack_executable;
@ -2454,9 +2446,7 @@ dl_main (const ElfW(Phdr) *phdr,
if (__glibc_unlikely (lossage != NULL)) if (__glibc_unlikely (lossage != NULL))
_dl_fatal_printf ("cannot set up thread-local storage: %s\n", _dl_fatal_printf ("cannot set up thread-local storage: %s\n",
lossage); lossage);
#if THREAD_GSCOPE_IN_TCB __tls_init_tp ();
list_add (&THREAD_SELF->list, &GL (dl_stack_user));
#endif
} }
/* Make sure no new search directories have been added. */ /* Make sure no new search directories have been added. */

View File

@ -1163,6 +1163,11 @@ extern void _dl_determine_tlsoffset (void) attribute_hidden;
number of audit modules are loaded. */ number of audit modules are loaded. */
void _dl_tls_static_surplus_init (size_t naudit) attribute_hidden; void _dl_tls_static_surplus_init (size_t naudit) attribute_hidden;
/* This function is called after processor-specific initialization of
the TCB and thread pointer via TLS_INIT_TP, to complete very early
initialization of the thread library. */
void __tls_init_tp (void) attribute_hidden;
#ifndef SHARED #ifndef SHARED
/* Set up the TCB for statically linked applications. This is called /* Set up the TCB for statically linked applications. This is called
early during startup because we always use TLS (for errno and the early during startup because we always use TLS (for errno and the

View File

@ -0,0 +1,30 @@
/* Completion of TCB initialization after TLS_INIT_TP. NPTL version.
Copyright (C) 2020-2021 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 <ldsodefs.h>
#include <list.h>
#include <tls.h>
void
__tls_init_tp (void)
{
/* Set up thread stack list management. */
INIT_LIST_HEAD (&GL (dl_stack_used));
INIT_LIST_HEAD (&GL (dl_stack_user));
list_add (&THREAD_SELF->list, &GL (dl_stack_user));
}