Fix TLS problems not handled by cherrypick

This commit is contained in:
Stan Shebs 2018-07-10 12:05:15 -07:00 committed by Fangrui Song
parent 3e9a530aae
commit c0ab16f8cc
5 changed files with 9 additions and 55 deletions

View File

@ -535,11 +535,10 @@ _dl_allocate_tls (void *mem)
rtld_hidden_def (_dl_allocate_tls)
void
internal_function
_dl_clear_dtv (dtv_t *dtv)
{
for (size_t cnt = 0; cnt < dtv[-1].counter; ++cnt)
if (! dtv[1 + cnt].pointer.is_static
if (/*! dtv[1 + cnt].pointer.is_static */ 1
&& dtv[1 + cnt].pointer.val != TLS_DTV_UNALLOCATED)
__signal_safe_free (dtv[1 + cnt].pointer.val);
memset (dtv, '\0', (dtv[-1].counter + 1) * sizeof (dtv_t));
@ -746,7 +745,6 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t *dtv, struct link_map *the_map)
the_map = listp->slotinfo[idx].map;
}
#if 0
sigset_t old;
_dl_mask_all_signals (&old);
@ -754,7 +752,6 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t *dtv, struct link_map *the_map)
reentrancy. */
if (dtv[GET_ADDR_MODULE].pointer.val != TLS_DTV_UNALLOCATED)
{
assert (dtv[GET_ADDR_MODULE].pointer.val != TLS_DTV_UNALLOCATED);
_dl_unmask_signals (&old);
return (char *) dtv[GET_ADDR_MODULE].pointer.val + GET_ADDR_OFFSET;
@ -778,48 +775,7 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t *dtv, struct link_map *the_map)
offset = the_map->l_tls_offset;
assert (offset != NO_TLS_OFFSET);
}
#endif
/* Make sure that, if a dlopen running in parallel forces the
variable into static storage, we'll wait until the address in the
static TLS block is set up, and use that. If we're undecided
yet, make sure we make the decision holding the lock as well. */
if (__glibc_unlikely (the_map->l_tls_offset
!= FORCED_DYNAMIC_TLS_OFFSET))
{
__rtld_lock_lock_recursive (GL(dl_load_lock));
if (__glibc_likely (the_map->l_tls_offset == NO_TLS_OFFSET))
{
the_map->l_tls_offset = FORCED_DYNAMIC_TLS_OFFSET;
__rtld_lock_unlock_recursive (GL(dl_load_lock));
}
else if (__glibc_likely (the_map->l_tls_offset
!= FORCED_DYNAMIC_TLS_OFFSET))
{
#if TLS_TCB_AT_TP
void *p = (char *) THREAD_SELF - the_map->l_tls_offset;
#elif TLS_DTV_AT_TP
void *p = (char *) THREAD_SELF + the_map->l_tls_offset + TLS_PRE_TCB_SIZE;
#else
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
#endif
__rtld_lock_unlock_recursive (GL(dl_load_lock));
dtv[GET_ADDR_MODULE].pointer.to_free = NULL;
dtv[GET_ADDR_MODULE].pointer.val = p;
return (char *) p + GET_ADDR_OFFSET;
}
else
__rtld_lock_unlock_recursive (GL(dl_load_lock));
}
struct dtv_pointer result = allocate_and_init (the_map);
dtv[GET_ADDR_MODULE].pointer = result;
assert (result.to_free != NULL);
return (char *) result.val + GET_ADDR_OFFSET;
#if 0
if (offset == FORCED_DYNAMIC_TLS_OFFSET)
{
allocate_and_init (&dtv[GET_ADDR_MODULE], the_map);
@ -835,7 +791,7 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t *dtv, struct link_map *the_map)
threads to initialize it. They'll eventually write
to pointer.val, at which point we know they've fully
completed initialization. */
atomic_delay ();
atomic_spin_nop ();
}
/* Make sure we've picked up their initialization of the actual
block; this pairs against the write barrier in
@ -847,7 +803,6 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t *dtv, struct link_map *the_map)
_dl_unmask_signals (&old);
return (char *) dtv[GET_ADDR_MODULE].pointer.val + GET_ADDR_OFFSET;
#endif
}

View File

@ -1243,6 +1243,7 @@ init_one_static_tls (struct pthread *curp, struct link_map *map)
memset (__mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size),
'\0', map->l_tls_blocksize - map->l_tls_initimage_size);
#if 0 /* still needed? dtv refs gone in current code */
/* Fill in the DTV slot so that a later LD/GD access will find it. */
dtv[map->l_tls_modid].pointer.is_static = true;
/* Pairs against the read barrier in tls_get_attr_tail, guaranteeing
@ -1250,7 +1251,7 @@ init_one_static_tls (struct pthread *curp, struct link_map *map)
initimage write. */
atomic_write_barrier ();
dtv[map->l_tls_modid].pointer.val = dest;
#endif
}
void

View File

@ -258,9 +258,9 @@ extern unsigned long int _dl_higher_prime_number (unsigned long int n)
uint64_t _dl_strtoul (const char *, char **) attribute_hidden;
/* Mask every signal, returning the previous sigmask in OLD. */
extern void _dl_mask_all_signals (sigset_t *old) internal_function;
extern void _dl_mask_all_signals (sigset_t *old);
/* Undo _dl_mask_all_signals. */
extern void _dl_unmask_signals (sigset_t *old) internal_function;
extern void _dl_unmask_signals (sigset_t *old);
/* Function used as argument for `_dl_receive_error' function. The
arguments are the error code, error string, and the objname the
@ -1103,7 +1103,7 @@ rtld_hidden_proto (_dl_allocate_tls_init)
/* Remove all allocated dynamic TLS regions from a DTV
for reuse by new thread. */
extern void _dl_clear_dtv (dtv_t *dtv) internal_function;
extern void _dl_clear_dtv (dtv_t *dtv);
rtld_hidden_proto (_dl_clear_dtv)
extern void *__signal_safe_memalign (size_t boundary, size_t size);

View File

@ -134,7 +134,6 @@ _dl_discover_osversion (void)
/* Mask every signal, returning the previous sigmask in OLD. */
void
internal_function
_dl_mask_all_signals (sigset_t *old)
{
int ret;
@ -165,7 +164,6 @@ _dl_mask_all_signals (sigset_t *old)
/* Return sigmask to what it was before a call to _dl_mask_all_signals. */
void
internal_function
_dl_unmask_signals (sigset_t *old)
{
int ret;

View File

@ -32,6 +32,6 @@ extern int _dl_discover_osversion (void) attribute_hidden;
# define HAVE_DL_DISCOVER_OSVERSION 1
#include <signal.h>
void _dl_mask_all_signals (sigset_t *) internal_function;
void _dl_unmask_all_signals (sigset_t *) internal_function;
void _dl_mask_all_signals (sigset_t *);
void _dl_unmask_all_signals (sigset_t *);
#endif