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:
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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[],
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
39
elf/dl-tls.c
39
elf/dl-tls.c
@ -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 */
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
|
@ -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 =
|
||||||
|
@ -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. */
|
||||||
|
@ -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
|
||||||
|
Reference in New Issue
Block a user