diff options
author | Ulrich Drepper <drepper@redhat.com> | 2002-02-09 01:41:44 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2002-02-09 01:41:44 +0000 |
commit | a52d15621f2f03891944550b0b71ff117e15c16a (patch) | |
tree | 14cace4b408dc7ee21138ad62550a2123445ad8a /sysdeps | |
parent | 013aafb7d098153e8df3a133ce6302c20396a33f (diff) | |
download | glibc-a52d15621f2f03891944550b0b71ff117e15c16a.tar glibc-a52d15621f2f03891944550b0b71ff117e15c16a.tar.gz glibc-a52d15621f2f03891944550b0b71ff117e15c16a.tar.bz2 glibc-a52d15621f2f03891944550b0b71ff117e15c16a.zip |
Update.
2002-02-08 Ulrich Drepper <drepper@redhat.com>
* elf/rtld.c (_dl_start_final): Install DTV explicitly.
(dl_main): Move dtv/static TLS handling before relocation.
Unconditionally call _dl_tlsoffset. Call _dl_allocate_tls and
TLS_INIT_TP to allocate and install the dtv/static TLS block.
* sysdeps/generic/dl-tls.c (_dl_determine_tlsoffset): If no object
so far uses TLS initialize GL(dl_tls_static_size) and
GL(dl_tls_static_align) to account for the TCB.
(_dl_allocate_tls): New function.
* sysdeps/generic/ldsodefs.h (rtld_global): Add
_dl_initial_dtv_malloced.
* configure.in: Test for __builtin_memset more realistically.
* csu/version.c (banner): If TLS support available say so.
Diffstat (limited to 'sysdeps')
-rw-r--r-- | sysdeps/generic/dl-tls.c | 84 | ||||
-rw-r--r-- | sysdeps/generic/ldsodefs.h | 5 |
2 files changed, 89 insertions, 0 deletions
diff --git a/sysdeps/generic/dl-tls.c b/sysdeps/generic/dl-tls.c index 5b4fdd8cf1..eb9a37bf95 100644 --- a/sysdeps/generic/dl-tls.c +++ b/sysdeps/generic/dl-tls.c @@ -18,6 +18,7 @@ 02111-1307 USA. */ #include <assert.h> +#include <stdlib.h> #include <tls.h> @@ -84,6 +85,16 @@ _dl_determine_tlsoffset (struct link_map *firstp) size_t max_align = 0; size_t offset; + if (GL(dl_initimage_list) == NULL) + { + /* None of the objects used at startup time uses TLS. We still + have to allocate the TCB adn dtv. */ + GL(dl_tls_static_size) = TLS_TCB_SIZE; + GL(dl_tls_static_align) = TLS_TCB_ALIGN; + + return; + } + # if TLS_TCB_AT_TP /* We simply start with zero. */ offset = 0; @@ -149,6 +160,79 @@ _dl_determine_tlsoffset (struct link_map *firstp) } +void * +internal_function +_dl_allocate_tls (void) +{ + void *result; + dtv_t *dtv; + + /* Allocate a correctly aligned chunk of memory. */ + /* XXX For now */ + assert (GL(dl_tls_static_align) <= GL(dl_pagesize)); +#ifdef MAP_ANON +# define _dl_zerofd (-1) +#else +# define _dl_zerofd GL(dl_zerofd) + if ((dl_zerofd) == -1) + GL(dl_zerofd) = _dl_sysdep_open_zero_fill (); +# define MAP_ANON 0 +#endif + result = __mmap (0, GL(dl_tls_static_size), PROT_READ|PROT_WRITE, + MAP_ANON|MAP_PRIVATE, _dl_zerofd, 0); + + dtv = (dtv_t *) malloc ((GL(dl_tls_max_dtv_idx) + 1) * sizeof (dtv_t)); + if (result != MAP_FAILED && dtv != NULL) + { + struct link_map *runp; + +# if TLS_TCB_AT_TP + /* The TCB follows the TLS blocks. */ + result = (char *) result + GL(dl_tls_static_size) - TLS_TCB_SIZE; +# endif + + /* XXX Fill in an correct generation number. */ + dtv[0].counter = 0; + + /* Initialize the memory from the initialization image list and clear + the BSS parts. */ + if (GL(dl_initimage_list) != NULL) + { + runp = GL(dl_initimage_list)->l_tls_nextimage; + do + { + assert (runp->l_tls_modid > 0); + assert (runp->l_tls_modid <= GL(dl_tls_max_dtv_idx)); +# if TLS_TCB_AT_TP + dtv[runp->l_tls_modid].pointer = result - runp->l_tls_offset; +# elif TLS_DTV_AT_TP + dtv[runp->l_tls_modid].pointer = result + runp->l_tls_offset; +# else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + + memset (__mempcpy (dtv[runp->l_tls_modid].pointer, + runp->l_tls_initimage, + runp->l_tls_initimage_size), + '\0', + runp->l_tls_blocksize - runp->l_tls_initimage_size); + } + while ((runp = runp->l_tls_nextimage) != NULL); + } + + /* Add the dtv to the thread data structures. */ + INSTALL_DTV (result, dtv); + } + else if (result != NULL) + { + free (result); + result = NULL; + } + + return result; +} + + /* The __tls_get_addr function has two basic forms which differ in the arguments. The IA-64 form takes two parameters, the module ID and offset. The form used, among others, on IA-32 takes a reference to diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index f049878cbd..e65865c068 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -303,6 +303,9 @@ struct rtld_global EXTERN size_t _dl_tls_static_size; /* Alignment requirement of the static TLS block. */ EXTERN size_t _dl_tls_static_align; + + /* True if the dtv for the initial thread was malloc()ed. */ + EXTERN bool _dl_initial_dtv_malloced; #endif /* Name of the shared object to be profiled (if any). */ @@ -666,6 +669,8 @@ extern size_t _dl_next_tls_modid (void) internal_function; extern void _dl_determine_tlsoffset (struct link_map *firstp) internal_function; +/* Allocate memory for static TLS block and dtv. */ +extern void *_dl_allocate_tls (void) internal_function; __END_DECLS |