about summary refs log tree commit diff
path: root/sysdeps/generic/dl-tls.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/generic/dl-tls.c')
-rw-r--r--sysdeps/generic/dl-tls.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/sysdeps/generic/dl-tls.c b/sysdeps/generic/dl-tls.c
index 850df8d76f..550de56530 100644
--- a/sysdeps/generic/dl-tls.c
+++ b/sysdeps/generic/dl-tls.c
@@ -110,6 +110,7 @@ _dl_next_tls_modid (void)
   return result;
 }
 
+# ifdef SHARED
 
 void
 internal_function
@@ -204,6 +205,41 @@ _dl_determine_tlsoffset (void)
 }
 
 
+/* This is called only when the data structure setup was skipped at startup,
+   when there was no need for it then.  Now we have dynamically loaded
+   something needing TLS, or libpthread needs it.  */
+int
+internal_function
+_dl_tls_setup (void)
+{
+  assert (GL(dl_tls_dtv_slotinfo_list) == NULL);
+  assert (GL(dl_tls_max_dtv_idx) == 0);
+
+  const size_t nelem = 2 + TLS_SLOTINFO_SURPLUS;
+
+  GL(dl_tls_dtv_slotinfo_list) =
+    malloc (sizeof (struct dtv_slotinfo_list)
+	    + nelem * sizeof (struct dtv_slotinfo));
+  if (GL(dl_tls_dtv_slotinfo_list) == NULL)
+    return -1;
+
+  memset (GL(dl_tls_dtv_slotinfo_list)->slotinfo, '\0',
+	  nelem * sizeof (struct dtv_slotinfo));
+  GL(dl_tls_dtv_slotinfo_list)->len = nelem;
+  GL(dl_tls_dtv_slotinfo_list)->next = NULL;
+
+  /* Number of elements in the static TLS block.  It can't be zero
+     because of various assumptions.  The one element is null.  */
+  GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx) = 1;
+
+  /* This initializes more variables for us.  */
+  _dl_determine_tlsoffset ();
+
+  return 0;
+}
+rtld_hidden_def (_dl_tls_setup)
+# endif
+
 static void *
 internal_function
 allocate_dtv (void *result)