2002-11-03 Roland McGrath <roland@redhat.com>

* sysdeps/generic/ldsodefs.h (struct rtld_global): New member
	`_dl_tls_static_used'.
	* sysdeps/generic/libc-tls.c (_dl_tls_static_used): New variable.
	(__libc_setup_tls): Initialize it.  Let the initial value of
	_dl_tls_static_size indicate some surplus space in the computed value.
	* elf/dl-open.c (_dl_tls_static_size): New variable.
	* sysdeps/generic/dl-tls.c (_dl_determine_tlsoffset): Initialize
	_dl_tls_static_used.  Add some surplus space into _dl_tls_static_size.
	* elf/dl-reloc.c [USE_TLS] (allocate_static_tls): New function.
	(CHECK_STATIC_TLS): Use it.
	* elf/dl-close.c (_dl_close): Adjust _dl_tls_static_used when the
	closed objects occupied a trailing contiguous chunk of static TLS area.
This commit is contained in:
Roland McGrath 2002-11-05 03:01:37 +00:00
parent 2f0f157e1c
commit c56baa872b
5 changed files with 63 additions and 10 deletions

View File

@ -34,6 +34,12 @@
#include <dl-dst.h>
#ifdef SHARED
/* Giving this initialized value preallocates some surplus bytes in the
static TLS area, see __libc_setup_tls (libc-tls.c). */
size_t _dl_tls_static_size = 576;
#endif
extern ElfW(Addr) _dl_sysdep_start (void **start_argptr,
void (*dl_main) (const ElfW(Phdr) *phdr,
ElfW(Word) phnum,

View File

@ -35,6 +35,33 @@
#endif
#ifdef USE_TLS
/* We are trying to perform a static TLS relocation in MAP, but it was
dynamically loaded. This can only work if there is enough surplus in
the static TLS area already allocated for each running thread. If this
object's TLS segment is too big to fit, we return false. If it fits,
we set MAP->l_tls_offset and return true. */
static bool
allocate_static_tls (struct link_map *map)
{
size_t offset = roundup (GL(dl_tls_static_used), map->l_tls_align);
if (offset + map->l_tls_blocksize > (GL(dl_tls_static_size)
# if TLS_TCB_AT_TP
- TLS_TCB_SIZE
# elif TLS_DTV_AT_TP
/* dl_tls_static_used includes the TCB at the beginning. */
# else
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
# endif
))
return false;
map->l_tls_offset = offset;
GL(dl_tls_static_used) = offset + map->l_tls_blocksize;
return true;
}
#endif
void
_dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
int lazy, int consider_profiling)
@ -159,9 +186,19 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
l->l_lookup_cache.value = _lr; })) \
: l->l_addr)
/* This macro is used as a callback from elf_machine_rel{a,} when a
static TLS reloc is about to be performed. Since (in dl-load.c) we
permit dynamic loading of objects that might use such relocs, we
have to check whether each use is actually doable. If the object
whose TLS segment the reference resolves to was allocated space in
the static TLS block at startup, then it's ok. Otherwise, we make
an attempt to allocate it in surplus space on the fly. If that
can't be done, we fall back to the error that DF_STATIC_TLS is
intended to produce. */
#define CHECK_STATIC_TLS(map, sym_map) \
do { \
if (__builtin_expect ((sym_map)->l_tls_offset == 0, 0)) \
if (__builtin_expect ((sym_map)->l_tls_offset == 0, 0) \
&& !allocate_static_tls (sym_map)) \
{ \
errstring = N_("shared object cannot be dlopen()ed"); \
INTUSE(_dl_signal_error) (0, (map)->l_name, NULL, errstring); \

View File

@ -31,6 +31,10 @@
# 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
/* Value used for dtv entries for which the allocation is delayed. */
# define TLS_DTV_UNALLOCATED ((void *) -1l)
@ -150,7 +154,9 @@ _dl_determine_tlsoffset (void)
// XXX would invalidate the offsets the linker creates for the LE
// XXX model.
GL(dl_tls_static_size) = offset + TLS_TCB_SIZE;
GL(dl_tls_static_used) = offset;
GL(dl_tls_static_size) = roundup (offset + TLS_STATIC_SURPLUS + TLS_TCB_SIZE,
TLS_TCB_ALIGN);
# elif TLS_DTV_AT_TP
/* The TLS blocks start right after the TCB. */
offset = TLS_TCB_SIZE;
@ -186,7 +192,9 @@ _dl_determine_tlsoffset (void)
offset += prev_size;
}
GL(dl_tls_static_size) = offset;
GL(dl_tls_static_used) = offset;
GL(dl_tls_static_size) = roundup (offset + TLS_STATIC_SURPLUS,
TLS_TCB_ALIGN);
# else
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
# endif

View File

@ -326,9 +326,6 @@ struct rtld_global
/* Number of additional slots in the dtv allocated. */
# define DTV_SURPLUS (14)
/* The value of _dl_tls_static_size is kept a multiple of this. */
# define TLS_STATIC_MIN (1024)
/* Initial dtv of the main thread, not allocated with normal malloc. */
EXTERN void *_dl_initial_dtv;
/* Generation counter for the dtv. */

View File

@ -182,12 +182,17 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign)
GL(dl_tls_max_dtv_idx) = 1;
GL(dl_tls_dtv_slotinfo_list) = &static_slotinfo.si;
/* That is the size of the TLS memory for this object. */
GL(dl_tls_static_size) = (roundup (memsz, align ?: 1)
memsz = roundup (memsz, align ?: 1);
# if TLS_TCB_AT_TP
+ tcbsize
memsz += tcbsize;
# endif
);
/* 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),
TLS_TCB_ALIGN);
GL(dl_tls_static_used) = memsz;
/* The alignment requirement for the static TLS block. */
GL(dl_tls_static_align) = MAX (TLS_TCB_ALIGN, max_align);
/* Number of elements in the static TLS block. */