diff options
author | Szabolcs Nagy <szabolcs.nagy@arm.com> | 2021-02-16 12:55:13 +0000 |
---|---|---|
committer | Szabolcs Nagy <szabolcs.nagy@arm.com> | 2021-04-13 08:43:40 +0100 |
commit | b116855de71098ef7dd2875dd3237f8f3ecc12c2 (patch) | |
tree | 6da94b9ca548a5042d743626fdbe1990fa5221a2 /sysdeps/x86_64/dl-tls.c | |
parent | f8ea2b9982e39fd950d157f5dba31121ceb51df3 (diff) | |
download | glibc-nsz/bug19329-v2.tar.gz glibc-nsz/bug19329-v2.tar.xz glibc-nsz/bug19329-v2.zip |
RFC elf: Fix slow tls access after dlopen [BZ #19924] nsz/bug19329-v2
In short: __tls_get_addr checks the global generation counter, _dl_update_slotinfo updates up to the generation of the accessed module. If the global generation is newer than geneneration of the module then __tls_get_addr keeps hitting the slow path that updates the dtv. Possible approaches i can see: 1. update to global generation instead of module, 2. check the module generation in the fast path. This patch is 1.: it needs additional sync (load acquire) so the slotinfo list is up to date with the observed global generation. Approach 2. would require walking the slotinfo list at all times. I don't know how to make that fast with many modules. Note: in the x86_64 version of dl-tls.c the generation is only loaded once, since relaxed mo is not faster than acquire mo load. I have not benchmarked this yet.
Diffstat (limited to 'sysdeps/x86_64/dl-tls.c')
-rw-r--r-- | sysdeps/x86_64/dl-tls.c | 4 |
1 files changed, 2 insertions, 2 deletions
diff --git a/sysdeps/x86_64/dl-tls.c b/sysdeps/x86_64/dl-tls.c index 24ef560b71..4ded8dd6b9 100644 --- a/sysdeps/x86_64/dl-tls.c +++ b/sysdeps/x86_64/dl-tls.c @@ -40,9 +40,9 @@ __tls_get_addr_slow (GET_ADDR_ARGS) { dtv_t *dtv = THREAD_DTV (); - size_t gen = atomic_load_relaxed (&GL(dl_tls_generation)); + size_t gen = atomic_load_acquire (&GL(dl_tls_generation)); if (__glibc_unlikely (dtv[0].counter != gen)) - return update_get_addr (GET_ADDR_PARAM); + return update_get_addr (GET_ADDR_PARAM, gen); return tls_get_addr_tail (GET_ADDR_PARAM, dtv, NULL); } |