summaryrefslogtreecommitdiff
path: root/elf/dl-tls.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2008-01-31 08:43:22 +0000
committerJakub Jelinek <jakub@redhat.com>2008-01-31 08:43:22 +0000
commita21d44637e4c53cce4760a2e2b13f0213c49a33d (patch)
treee28730f085cf343d98da117b41773940b365dd37 /elf/dl-tls.c
parent07b7d301cc62d3f4ff1bbaf668ddc2510f7a55d8 (diff)
Updated to fedora-glibc-20080131T0821cvs/fedora-glibc-2_7_90-4
Diffstat (limited to 'elf/dl-tls.c')
-rw-r--r--elf/dl-tls.c26
1 files changed, 25 insertions, 1 deletions
diff --git a/elf/dl-tls.c b/elf/dl-tls.c
index d5865ab409..3059481043 100644
--- a/elf/dl-tls.c
+++ b/elf/dl-tls.c
@@ -413,7 +413,8 @@ _dl_allocate_tls_init (void *result)
not be the generation counter. */
maxgen = MAX (maxgen, listp->slotinfo[cnt].gen);
- if (map->l_tls_offset == NO_TLS_OFFSET)
+ if (map->l_tls_offset == NO_TLS_OFFSET
+ || map->l_tls_offset == FORCED_DYNAMIC_TLS_OFFSET)
{
/* For dynamically loaded modules we simply store
the value indicating deferred allocation. */
@@ -702,6 +703,7 @@ __tls_get_addr (GET_ADDR_ARGS)
if (__builtin_expect (dtv[0].counter != GL(dl_tls_generation), 0))
the_map = _dl_update_slotinfo (GET_ADDR_MODULE);
+ retry:
p = dtv[GET_ADDR_MODULE].pointer.val;
if (__builtin_expect (p == TLS_DTV_UNALLOCATED, 0))
@@ -722,6 +724,28 @@ __tls_get_addr (GET_ADDR_ARGS)
the_map = listp->slotinfo[idx].map;
}
+ /* 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 (__builtin_expect (the_map->l_tls_offset
+ != FORCED_DYNAMIC_TLS_OFFSET, 0))
+ {
+ __rtld_lock_lock_recursive (GL(dl_load_lock));
+ if (__builtin_expect (the_map->l_tls_offset == NO_TLS_OFFSET, 1))
+ {
+ the_map->l_tls_offset = FORCED_DYNAMIC_TLS_OFFSET;
+ __rtld_lock_unlock_recursive (GL(dl_load_lock));
+ }
+ else
+ {
+ __rtld_lock_unlock_recursive (GL(dl_load_lock));
+ if (__builtin_expect (the_map->l_tls_offset
+ != FORCED_DYNAMIC_TLS_OFFSET, 1))
+ goto retry;
+ }
+ }
p = dtv[GET_ADDR_MODULE].pointer.val = allocate_and_init (the_map);
dtv[GET_ADDR_MODULE].pointer.is_static = false;
}