svn commit: branches/uClibc-nptl/ldso/ldso

sjhill at uclibc.org sjhill at uclibc.org
Sun Nov 6 05:46:29 UTC 2005


Author: sjhill
Date: 2005-11-05 21:46:27 -0800 (Sat, 05 Nov 2005)
New Revision: 12171

Log:
Implemented '_dl_allocate_static_tls' function for TLS relocations.


Modified:
   branches/uClibc-nptl/ldso/ldso/dl-tls.c


Changeset:
Modified: branches/uClibc-nptl/ldso/ldso/dl-tls.c
===================================================================
--- branches/uClibc-nptl/ldso/ldso/dl-tls.c	2005-11-06 05:25:52 UTC (rev 12170)
+++ branches/uClibc-nptl/ldso/ldso/dl-tls.c	2005-11-06 05:46:27 UTC (rev 12171)
@@ -26,16 +26,6 @@
  * SUCH DAMAGE.
  */
 
-/*
- * The big TODO list:
- *
- *    - Environment variables LD_TRACE_LOADED_OBJECTS and LD_PRELOAD
- *      need to be supported.
- *    - Config option LDSO_PRELOAD_FILE_SUPPORT needs to be supported.
- *    - Support TLS information for 'ldd' command.
- *
- */
-
 #include <tls.h>
 #include <dl-tls.h>
 #include <ldsodefs.h>
@@ -46,6 +36,7 @@
 void (*_dl_free_function) (void *__ptr) = NULL;
 
 void *_dl_memalign (size_t __boundary, size_t __size);
+struct link_map *_dl_update_slotinfo (unsigned long int req_modid);
 
 void *
 _dl_calloc (size_t __nmemb, size_t __size)
@@ -85,7 +76,9 @@
 	if (_dl_free_function)
 		(*_dl_free_function) (__ptr);
 
-	_dl_debug_early("Unable to free memory used for TLS\n");
+#if 0
+	_dl_debug_early("NOT IMPLEMENTED PROPERLY!!!\n");
+#endif
 }
 
 
@@ -122,13 +115,81 @@
 			_dl_allocate_static_tls (sym_map);								\
 	} while (0)
 
-void 
+/*
+ * 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 fail.  If it fits,
+ * we set MAP->l_tls_offset and return.
+ * This function intentionally does not return any value but signals error
+ * directly, as static TLS should be rare and code handling it should
+ * not be inlined as much as possible.
+ */
+void
 internal_function __attribute_noinline__
 _dl_allocate_static_tls (struct link_map *map)
 {
-	_dl_dprintf(2, "_dl_allocate_static_tls NOT IMPLEMENTED!\n");
-	_dl_exit(1);
-	return;
+	/* If the alignment requirements are too high fail.  */
+	if (map->l_tls_align > _dl_tls_static_align)
+	{
+fail:
+		_dl_dprintf(2, "cannot allocate memory in static TLS block");
+		_dl_exit(30);
+	}
+
+# if TLS_TCB_AT_TP
+	size_t freebytes;
+	size_t n;
+	size_t blsize;
+
+	freebytes = _dl_tls_static_size - _dl_tls_static_used - TLS_TCB_SIZE;
+
+	blsize = map->l_tls_blocksize + map->l_tls_firstbyte_offset;
+	if (freebytes < blsize)
+		goto fail;
+
+	n = (freebytes - blsize) / map->l_tls_align;
+
+	size_t offset = _dl_tls_static_used + (freebytes - n * map->l_tls_align
+		- map->l_tls_firstbyte_offset);
+
+	map->l_tls_offset = _dl_tls_static_used = offset;
+# elif TLS_DTV_AT_TP
+	size_t used;
+	size_t check;
+
+	size_t offset = roundup (_dl_tls_static_used, map->l_tls_align);
+	used = offset + map->l_tls_blocksize;
+	check = used;
+
+	/* dl_tls_static_used includes the TCB at the beginning. */
+	if (check > _dl_tls_static_size)
+		goto fail;
+
+	map->l_tls_offset = offset;
+	_dl_tls_static_used = used;
+# else
+#  error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+# endif
+
+	/*
+	 * If the object is not yet relocated we cannot initialize the
+	 * static TLS region.  Delay it.
+	 */
+	if (((struct elf_resolve *) map)->init_flag & RELOCS_DONE)
+    {
+#ifdef SHARED
+		/*
+		 * Update the slot information data for at least the generation of
+		 * the DSO we are allocating data for.
+		 */
+		if (__builtin_expect (THREAD_DTV()[0].counter != _dl_tls_generation, 0))
+			(void) _dl_update_slotinfo (map->l_tls_modid);
+#endif
+		_dl_init_static_tls (map);
+	}
+	else
+		map->l_need_tls_init = 1;
 }
 
 /* Initialize static TLS area and DTV for current (only) thread.
@@ -150,7 +211,7 @@
 	dtv_t *dtv = THREAD_DTV ();
 	if (!(map->l_tls_modid <= dtv[-1].counter)) {
 		_dl_dprintf(2, "map->l_tls_modid <= dtv[-1].counter FAILED!\n");
-		_dl_exit(1);
+		_dl_exit(30);
 	}
 	dtv[map->l_tls_modid].pointer.val = dest;
 	dtv[map->l_tls_modid].pointer.is_static = true;
@@ -415,11 +476,7 @@
      initial set of modules.  This should avoid in most cases expansions
      of the dtv.  */
   dtv_length = _dl_tls_max_dtv_idx + DTV_SURPLUS;
-#ifndef __UCLIBC__
-  dtv = calloc (dtv_length + 2, sizeof (dtv_t));
-#else
   dtv = _dl_calloc (dtv_length + 2, sizeof (dtv_t));
-#endif
   if (dtv != NULL)
     {
       /* This is the initial length of the dtv.  */
@@ -936,22 +993,8 @@
 
 	/* Fill in the information from the loaded modules.  No namespace
 	   but the base one can be filled at this time.  */
-#ifndef __UCLIBC__
-	_dl_assert (_dl_ns[LM_ID_BASE + 1]._ns_loaded == NULL);
 	int i = 0;
 	struct link_map *l;
-	for (l = _dl_ns[LM_ID_BASE]._ns_loaded; l != NULL; l = l->l_next)
-		if (l->l_tls_blocksize != 0)
-		{
-			/* This is a module with TLS data.  Store the map reference.
-			   The generation counter is zero.  */
-			slotinfo[i].map = l;
-			/* slotinfo[i].gen = 0; */
-		++i;
-		}
-#else
-	int i = 0;
-	struct link_map *l;
 	for (l =  (struct link_map *) _dl_loaded_modules; l != NULL; l = l->l_next)
 		if (l->l_tls_blocksize != 0)
 		{
@@ -961,7 +1004,6 @@
 			/* slotinfo[i].gen = 0; */
 		++i;
 		}
-#endif
 	_dl_assert (i == _dl_tls_max_dtv_idx);
 
 	/* Compute the TLS offsets for the various blocks.  */




More information about the uClibc-cvs mailing list