aboutsummaryrefslogtreecommitdiff
path: root/elf/dl-tls.c
diff options
context:
space:
mode:
Diffstat (limited to 'elf/dl-tls.c')
-rw-r--r--elf/dl-tls.c55
1 files changed, 50 insertions, 5 deletions
diff --git a/elf/dl-tls.c b/elf/dl-tls.c
index ca13778ca9..924ee5d989 100644
--- a/elf/dl-tls.c
+++ b/elf/dl-tls.c
@@ -29,10 +29,54 @@
#include <dl-tls.h>
#include <ldsodefs.h>
-/* Amount of excess space to allocate in the static TLS area
- to allow dynamic loading of modules defining IE-model TLS data. */
-#define TLS_STATIC_SURPLUS 64 + DL_NNS * 176
+#define TUNABLE_NAMESPACE rtld
+#include <dl-tunables.h>
+
+/* Surplus static TLS, GLRO(dl_tls_static_surplus), is used for
+
+ - IE TLS in libc.so for all dlmopen namespaces except in the initial
+ one where libc.so is not loaded dynamically but at startup time,
+ - IE TLS in other libraries which may be dynamically loaded even in the
+ initial namespace,
+ - and optionally for optimizing dynamic TLS access.
+
+ The maximum number of namespaces is DL_NNS, but to support that many
+ namespaces correctly the static TLS allocation should be significantly
+ increased, which may cause problems with small thread stacks due to the
+ way static TLS is accounted (bug 11787).
+
+ So there is a rtld.nns tunable limit on the number of supported namespaces
+ that affects the size of the static TLS and by default it's small enough
+ not to cause problems with existing applications. The limit is not
+ enforced or checked: it is the user's responsibility to increase rtld.nns
+ if more dlmopen namespaces are used. */
+
+/* Size of initial-exec TLS in libc.so. */
+#define LIBC_IE_TLS 192
+/* Size of initial-exec TLS in libraries other than libc.so.
+ This should be large enough to cover runtime libraries of the
+ compiler such as libgomp and libraries in libc other than libc.so. */
+#define OTHER_IE_TLS 144
+/* Size of additional surplus TLS, placeholder for TLS optimizations. */
+#define OPT_SURPLUS_TLS 512
+void
+_dl_tls_static_surplus_init (void)
+{
+ size_t nns;
+
+#if HAVE_TUNABLES
+ nns = TUNABLE_GET (nns, size_t, NULL);
+#else
+ /* Default values of the tunables. */
+ nns = 4;
+#endif
+ if (nns > DL_NNS)
+ nns = DL_NNS;
+ GLRO(dl_tls_static_surplus) = ((nns - 1) * LIBC_IE_TLS
+ + nns * OTHER_IE_TLS
+ + OPT_SURPLUS_TLS);
+}
/* Out-of-memory handler. */
static void
@@ -224,7 +268,8 @@ _dl_determine_tlsoffset (void)
}
GL(dl_tls_static_used) = offset;
- GL(dl_tls_static_size) = (roundup (offset + TLS_STATIC_SURPLUS, max_align)
+ GL(dl_tls_static_size) = (roundup (offset + GLRO(dl_tls_static_surplus),
+ max_align)
+ TLS_TCB_SIZE);
#elif TLS_DTV_AT_TP
/* The TLS blocks start right after the TCB. */
@@ -268,7 +313,7 @@ _dl_determine_tlsoffset (void)
}
GL(dl_tls_static_used) = offset;
- GL(dl_tls_static_size) = roundup (offset + TLS_STATIC_SURPLUS,
+ GL(dl_tls_static_size) = roundup (offset + GLRO(dl_tls_static_surplus),
TLS_TCB_ALIGN);
#else
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"