aboutsummaryrefslogtreecommitdiff
path: root/sysdeps
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2002-02-09 01:41:44 +0000
committerUlrich Drepper <drepper@redhat.com>2002-02-09 01:41:44 +0000
commita52d15621f2f03891944550b0b71ff117e15c16a (patch)
tree14cace4b408dc7ee21138ad62550a2123445ad8a /sysdeps
parent013aafb7d098153e8df3a133ce6302c20396a33f (diff)
downloadglibc-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.c84
-rw-r--r--sysdeps/generic/ldsodefs.h5
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