From 0c7b002fac12dcb2f53ba83ee56bb3b5d2439447 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Tue, 9 Jun 2020 09:57:28 +0100 Subject: rtld: Add rtld.nns tunable for the number of supported namespaces TLS_STATIC_SURPLUS is 1664 bytes currently which is not enough to support DL_NNS (== 16) number of dynamic link namespaces, if we assume 192 bytes of TLS are reserved for libc use and 144 bytes are reserved for other system libraries that use IE TLS. A new tunable is introduced to control the number of supported namespaces and to adjust the surplus static TLS size as follows: surplus_tls = 192 * (rtld.nns-1) + 144 * rtld.nns + 512 The default is rtld.nns == 4 and then the surplus TLS size is the same as before, so the behaviour is unchanged by default. If an application creates more namespaces than the rtld.nns setting allows, then it is not guaranteed to work, but the limit is not checked. So existing usage will continue to work, but in the future if an application creates more than 4 dynamic link namespaces then the tunable will need to be set. In this patch DL_NNS is a fixed value and provides a maximum to the rtld.nns setting. Static linking used fixed 2048 bytes surplus TLS, this is changed so the same contract is used as for dynamic linking. With static linking DL_NNS == 1 so rtld.nns tunable is forced to 1, so by default the surplus TLS is reduced to 144 + 512 = 656 bytes. This change is not expected to cause problems. Tested on aarch64-linux-gnu and x86_64-linux-gnu. Reviewed-by: Carlos O'Donell --- csu/libc-tls.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'csu') diff --git a/csu/libc-tls.c b/csu/libc-tls.c index 73ade0f..e260315 100644 --- a/csu/libc-tls.c +++ b/csu/libc-tls.c @@ -46,13 +46,16 @@ bool _dl_tls_dtv_gaps; struct dtv_slotinfo_list *_dl_tls_dtv_slotinfo_list; /* Number of modules in the static TLS block. */ size_t _dl_tls_static_nelem; -/* Size of the static TLS block. Giving this initialized value - preallocates some surplus bytes in the static TLS area. */ -size_t _dl_tls_static_size = 2048; +/* Size of the static TLS block. */ +size_t _dl_tls_static_size; /* Size actually allocated in the static TLS block. */ size_t _dl_tls_static_used; /* Alignment requirement of the static TLS block. */ size_t _dl_tls_static_align; +/* Size of surplus space in the static TLS area for dynamically + loaded modules with IE-model TLS or for TLSDESC optimization. + See comments in elf/dl-tls.c where it is initialized. */ +size_t _dl_tls_static_surplus; /* Generation counter for the dtv. */ size_t _dl_tls_generation; @@ -81,10 +84,8 @@ init_slotinfo (void) static void init_static_tls (size_t memsz, size_t align) { - /* That is the size of the TLS memory for this object. The initialized - value of _dl_tls_static_size is provided by dl-open.c to request some - surplus that permits dynamic loading of modules with IE-model TLS. */ - GL(dl_tls_static_size) = roundup (memsz + GL(dl_tls_static_size), + /* That is the size of the TLS memory for this object. */ + GL(dl_tls_static_size) = roundup (memsz + GLRO(dl_tls_static_surplus), TLS_TCB_ALIGN); #if TLS_TCB_AT_TP GL(dl_tls_static_size) += TLS_TCB_SIZE; @@ -125,25 +126,24 @@ __libc_setup_tls (void) break; } + /* Calculate the size of the static TLS surplus. */ + _dl_tls_static_surplus_init (); + /* We have to set up the TCB block which also (possibly) contains 'errno'. Therefore we avoid 'malloc' which might touch 'errno'. Instead we use 'sbrk' which would only uses 'errno' if it fails. In this case we are right away out of memory and the user gets - what she/he deserves. - - The initialized value of _dl_tls_static_size is provided by dl-open.c - to request some surplus that permits dynamic loading of modules with - IE-model TLS. */ + what she/he deserves. */ #if TLS_TCB_AT_TP /* Align the TCB offset to the maximum alignment, as _dl_allocate_tls_storage (in elf/dl-tls.c) does using __libc_memalign and dl_tls_static_align. */ - tcb_offset = roundup (memsz + GL(dl_tls_static_size), max_align); + tcb_offset = roundup (memsz + GLRO(dl_tls_static_surplus), max_align); tlsblock = __sbrk (tcb_offset + TLS_INIT_TCB_SIZE + max_align); #elif TLS_DTV_AT_TP tcb_offset = roundup (TLS_INIT_TCB_SIZE, align ?: 1); tlsblock = __sbrk (tcb_offset + memsz + max_align - + TLS_PRE_TCB_SIZE + GL(dl_tls_static_size)); + + TLS_PRE_TCB_SIZE + GLRO(dl_tls_static_surplus)); tlsblock += TLS_PRE_TCB_SIZE; #else /* In case a model with a different layout for the TCB and DTV -- cgit v1.1