diff options
author | Siddhesh Poyarekar <siddhesh@redhat.com> | 2015-07-24 19:13:38 +0530 |
---|---|---|
committer | Siddhesh Poyarekar <siddhesh@redhat.com> | 2015-07-24 19:13:38 +0530 |
commit | e400f3ccd36fe91d432cc7d45b4ccc799dece763 (patch) | |
tree | b586fda337c690401881f8e805bbdd542ce48023 /Makeconfig | |
parent | 48f5f7a63c5971a698ac2b97e4c383e04cbbe110 (diff) | |
download | glibc-e400f3ccd36fe91d432cc7d45b4ccc799dece763.tar.gz glibc-e400f3ccd36fe91d432cc7d45b4ccc799dece763.tar.xz glibc-e400f3ccd36fe91d432cc7d45b4ccc799dece763.zip |
Use IE model for static variables in libc.so, libpthread.so and rtld
The recently introduced TLS variables in the thread-local destructor implementation (__cxa_thread_atexit_impl) used the default GD access model, resulting in a call to __tls_get_addr. This causes a deadlock with recent changes to the way TLS is initialized because DTV allocations are delayed and hence despite knowing the offset to the variable inside its TLS block, the thread has to take the global rtld lock to safely update the TLS offset. This causes deadlocks when a thread is instantiated and joined inside a destructor of a dlopen'd DSO. The correct long term fix is to somehow not take the lock, but that will need a lot deeper change set to alter the way in which the big rtld lock is used. Instead, this patch just eliminates the call to __tls_get_addr for the thread-local variables inside libc.so, libpthread.so and rtld by building all of their units with -mtls-model=initial-exec. There were concerns that the static storage for TLS is limited and hence we should not be using it. Additionally, dynamically loaded modules may result in libc.so looking for this static storage pretty late in static binaries. Both concerns are valid when using TLSDESC since that is where one may attempt to allocate a TLS block from static storage for even those variables that are not IE. They're not very strong arguments for the traditional TLS model though, since it assumes that the static storage would be used sparingly and definitely not by default. Hence, for now this would only theoretically affect ARM architectures. The impact is hence limited to statically linked binaries that dlopen modules that in turn load libc.so, all that on arm hardware. It seems like a small enough impact to justify fixing the larger problem that currently affects everything everywhere. This still does not solve the original problem completely. That is, it is still possible to deadlock on the big rtld lock with a small tweak to the test case attached to this patch. That problem is however not a regression in 2.22 and hence could be tackled as a separate project. The test case is picked up as is from Alex's patch. This change has been tested to verify that it does not cause any issues on x86_64. ChangeLog: [BZ #18457] * nptl/Makefile (tests): New test case tst-join7. (modules-names): New test case module tst-join7mod. * nptl/tst-join7.c: New file. * nptl/tst-join7mod.c: New file. * Makeconfig (tls-model): Pass -ftls-model=initial-exec for all translation units in libc.so, libpthread.so and rtld.
Diffstat (limited to 'Makeconfig')
-rw-r--r-- | Makeconfig | 6 |
1 files changed, 5 insertions, 1 deletions
diff --git a/Makeconfig b/Makeconfig index 7b46323bd2..f136b88da1 100644 --- a/Makeconfig +++ b/Makeconfig @@ -858,6 +858,10 @@ in-module = $(subst -,_,$(firstword $(libof-$(basename $(@F))) \ $(libof-$(@F)) \ libc)) +# Build ld.so, libc.so and libpthread.so with -ftls-model=initial-exec +tls-model = $(if $(filter libpthread rtld \ + libc,$(in-module)),-ftls-model=initial-exec,) + module-cppflags-real = -include $(common-objpfx)libc-modules.h \ -DMODULE_NAME=$(in-module) @@ -883,7 +887,7 @@ CPPFLAGS = $(config-extra-cppflags) $(CPPUNDEFS) $(CPPFLAGS-config) \ override CFLAGS = -std=gnu99 $(gnu89-inline-CFLAGS) $(config-extra-cflags) \ $(filter-out %frame-pointer,$(+cflags)) $(+gccwarn-c) \ $(sysdep-CFLAGS) $(CFLAGS-$(suffix $@)) $(CFLAGS-$(<F)) \ - $(CFLAGS-$(@F)) \ + $(CFLAGS-$(@F)) $(tls-model) \ $(foreach lib,$(libof-$(basename $(@F))) \ $(libof-$(<F)) $(libof-$(@F)),$(CFLAGS-$(lib))) override CXXFLAGS = $(c++-sysincludes) \ |