1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-29 11:41:21 +03:00

elf, nptl: Initialize static TLS directly in ld.so

The stack list is available in ld.so since commit
1daccf403b ("nptl: Move stack list
variables into _rtld_global"), so it's possible to walk the stack
list directly in ld.so and perform the initialization there.

This eliminates an unprotected function pointer from _rtld_global
and reduces the libpthread initialization code.
This commit is contained in:
Florian Weimer
2021-05-05 06:20:31 +02:00
parent 2c71177309
commit 7cbf1c8416
9 changed files with 65 additions and 44 deletions

View File

@ -426,7 +426,7 @@ TLS generation counter wrapped! Please report this."));
_dl_update_slotinfo (imap->l_tls_modid); _dl_update_slotinfo (imap->l_tls_modid);
#endif #endif
GL(dl_init_static_tls) (imap); dl_init_static_tls (imap);
assert (imap->l_need_tls_init == 0); assert (imap->l_need_tls_init == 0);
} }
} }

View File

@ -118,7 +118,7 @@ _dl_try_allocate_static_tls (struct link_map *map, bool optional)
(void) _dl_update_slotinfo (map->l_tls_modid); (void) _dl_update_slotinfo (map->l_tls_modid);
#endif #endif
GL(dl_init_static_tls) (map); dl_init_static_tls (map);
} }
else else
map->l_need_tls_init = 1; map->l_need_tls_init = 1;
@ -141,6 +141,7 @@ cannot allocate memory in static TLS block"));
} }
} }
#if !THREAD_GSCOPE_IN_TCB
/* Initialize static TLS area and DTV for current (only) thread. /* Initialize static TLS area and DTV for current (only) thread.
libpthread implementations should provide their own hook libpthread implementations should provide their own hook
to handle all threads. */ to handle all threads. */
@ -159,7 +160,7 @@ _dl_nothread_init_static_tls (struct link_map *map)
memset (__mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size), memset (__mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size),
'\0', map->l_tls_blocksize - map->l_tls_initimage_size); '\0', map->l_tls_blocksize - map->l_tls_initimage_size);
} }
#endif /* !THREAD_GSCOPE_IN_TCB */
void void
_dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],

View File

@ -138,8 +138,6 @@ void *_dl_random;
#include <dl-procruntime.c> #include <dl-procruntime.c>
#include <dl-procinfo.c> #include <dl-procinfo.c>
void (*_dl_init_static_tls) (struct link_map *) = &_dl_nothread_init_static_tls;
size_t _dl_pagesize = EXEC_PAGESIZE; size_t _dl_pagesize = EXEC_PAGESIZE;
size_t _dl_minsigstacksize = CONSTANT_MINSIGSTKSZ; size_t _dl_minsigstacksize = CONSTANT_MINSIGSTKSZ;
@ -197,6 +195,7 @@ list_t _dl_stack_user;
int _dl_stack_cache_lock; int _dl_stack_cache_lock;
#else #else
int _dl_thread_gscope_count; int _dl_thread_gscope_count;
void (*_dl_init_static_tls) (struct link_map *) = &_dl_nothread_init_static_tls;
#endif #endif
struct dl_scope_free_list *_dl_scope_free_list; struct dl_scope_free_list *_dl_scope_free_list;

View File

@ -29,6 +29,10 @@
#include <dl-tls.h> #include <dl-tls.h>
#include <ldsodefs.h> #include <ldsodefs.h>
#if THREAD_GSCOPE_IN_TCB
# include <list.h>
#endif
#define TUNABLE_NAMESPACE rtld #define TUNABLE_NAMESPACE rtld
#include <dl-tunables.h> #include <dl-tunables.h>
@ -1005,3 +1009,38 @@ cannot create TLS data structures"));
listp->slotinfo[idx].gen = GL(dl_tls_generation) + 1; listp->slotinfo[idx].gen = GL(dl_tls_generation) + 1;
} }
} }
#if THREAD_GSCOPE_IN_TCB
static inline void __attribute__((always_inline))
init_one_static_tls (struct pthread *curp, struct link_map *map)
{
# if TLS_TCB_AT_TP
void *dest = (char *) curp - map->l_tls_offset;
# elif TLS_DTV_AT_TP
void *dest = (char *) curp + map->l_tls_offset + TLS_PRE_TCB_SIZE;
# else
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
# endif
/* Initialize the memory. */
memset (__mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size),
'\0', map->l_tls_blocksize - map->l_tls_initimage_size);
}
void
_dl_init_static_tls (struct link_map *map)
{
lll_lock (GL (dl_stack_cache_lock), LLL_PRIVATE);
/* Iterate over the list with system-allocated threads first. */
list_t *runp;
list_for_each (runp, &GL (dl_stack_used))
init_one_static_tls (list_entry (runp, struct pthread, list), map);
/* Now the list with threads using user-allocated stacks. */
list_for_each (runp, &GL (dl_stack_user))
init_one_static_tls (list_entry (runp, struct pthread, list), map);
lll_unlock (GL (dl_stack_cache_lock), LLL_PRIVATE);
}
#endif /* THREAD_GSCOPE_IN_TCB */

View File

@ -1139,7 +1139,9 @@ dl_main (const ElfW(Phdr) *phdr,
struct dl_main_state state; struct dl_main_state state;
dl_main_state_init (&state); dl_main_state_init (&state);
#if !THREAD_GSCOPE_IN_TCB
GL(dl_init_static_tls) = &_dl_nothread_init_static_tls; GL(dl_init_static_tls) = &_dl_nothread_init_static_tls;
#endif
#if defined SHARED && defined _LIBC_REENTRANT \ #if defined SHARED && defined _LIBC_REENTRANT \
&& defined __rtld_lock_default_lock_recursive && defined __rtld_lock_default_lock_recursive

View File

@ -951,38 +951,3 @@ __reclaim_stacks (void)
GL (dl_stack_cache_lock) = LLL_LOCK_INITIALIZER; GL (dl_stack_cache_lock) = LLL_LOCK_INITIALIZER;
__default_pthread_attr_lock = LLL_LOCK_INITIALIZER; __default_pthread_attr_lock = LLL_LOCK_INITIALIZER;
} }
static inline void __attribute__((always_inline))
init_one_static_tls (struct pthread *curp, struct link_map *map)
{
# if TLS_TCB_AT_TP
void *dest = (char *) curp - map->l_tls_offset;
# elif TLS_DTV_AT_TP
void *dest = (char *) curp + map->l_tls_offset + TLS_PRE_TCB_SIZE;
# else
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
# endif
/* Initialize the memory. */
memset (__mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size),
'\0', map->l_tls_blocksize - map->l_tls_initimage_size);
}
void
attribute_hidden
__pthread_init_static_tls (struct link_map *map)
{
lll_lock (GL (dl_stack_cache_lock), LLL_PRIVATE);
/* Iterate over the list with system-allocated threads first. */
list_t *runp;
list_for_each (runp, &GL (dl_stack_used))
init_one_static_tls (list_entry (runp, struct pthread, list), map);
/* Now the list with threads using user-allocated stacks. */
list_for_each (runp, &GL (dl_stack_user))
init_one_static_tls (list_entry (runp, struct pthread, list), map);
lll_unlock (GL (dl_stack_cache_lock), LLL_PRIVATE);
}

View File

@ -191,8 +191,6 @@ __pthread_initialize_minimal_internal (void)
GL(dl_make_stack_executable_hook) = &__make_stacks_executable; GL(dl_make_stack_executable_hook) = &__make_stacks_executable;
#endif #endif
GL(dl_init_static_tls) = &__pthread_init_static_tls;
/* Register the fork generation counter with the libc. */ /* Register the fork generation counter with the libc. */
#ifndef TLS_MULTIPLE_THREADS_IN_TCB #ifndef TLS_MULTIPLE_THREADS_IN_TCB
__libc_multiple_threads_ptr = __libc_multiple_threads_ptr =

View File

@ -381,8 +381,6 @@ extern int __pthread_multiple_threads attribute_hidden;
extern int *__libc_multiple_threads_ptr attribute_hidden; extern int *__libc_multiple_threads_ptr attribute_hidden;
#endif #endif
extern void __pthread_init_static_tls (struct link_map *) attribute_hidden;
extern size_t __pthread_get_minstack (const pthread_attr_t *attr); extern size_t __pthread_get_minstack (const pthread_attr_t *attr);
/* Namespace save aliases. */ /* Namespace save aliases. */

View File

@ -464,7 +464,9 @@ struct rtld_global
/* Generation counter for the dtv. */ /* Generation counter for the dtv. */
EXTERN size_t _dl_tls_generation; EXTERN size_t _dl_tls_generation;
#if !THREAD_GSCOPE_IN_TCB
EXTERN void (*_dl_init_static_tls) (struct link_map *); EXTERN void (*_dl_init_static_tls) (struct link_map *);
#endif
/* Scopes to free after next THREAD_GSCOPE_WAIT (). */ /* Scopes to free after next THREAD_GSCOPE_WAIT (). */
EXTERN struct dl_scope_free_list EXTERN struct dl_scope_free_list
@ -1270,6 +1272,23 @@ extern void _dl_non_dynamic_init (void)
extern void _dl_aux_init (ElfW(auxv_t) *av) extern void _dl_aux_init (ElfW(auxv_t) *av)
attribute_hidden; attribute_hidden;
/* Initialize the static TLS space for the link map in all existing
threads. */
#if THREAD_GSCOPE_IN_TCB
void _dl_init_static_tls (struct link_map *map) attribute_hidden;
#endif
static inline void
dl_init_static_tls (struct link_map *map)
{
#if THREAD_GSCOPE_IN_TCB
/* The stack list is available to ld.so, so the initialization can
be handled within ld.so directly. */
_dl_init_static_tls (map);
#else
GL (dl_init_static_tls) (map);
#endif
}
/* Return true if the ld.so copy in this namespace is actually active /* Return true if the ld.so copy in this namespace is actually active
and working. If false, the dl_open/dlfcn hooks have to be used to and working. If false, the dl_open/dlfcn hooks have to be used to
call into the outer dynamic linker (which happens after static call into the outer dynamic linker (which happens after static