فهرست منبع

separate __tls_get_addr implementation from dynamic linker/init_tls

such separation serves multiple purposes:

- by having the common path for __tls_get_addr alone in its own
  function with a tail call to the slow case, code generation is
  greatly improved.

- by having __tls_get_addr in it own file, it can be replaced on a
  per-arch basis as needed, for optimization or ABI-specific purposes.

- by removing __tls_get_addr from __init_tls.c, a few bytes of code
  are shaved off of static binaries (which are unlikely to use this
  function unless the linker messed up).
Rich Felker 11 سال پیش
والد
کامیت
5ba238e1e4
3فایلهای تغییر یافته به همراه23 افزوده شده و 11 حذف شده
  1. 0 5
      src/env/__init_tls.c
  2. 6 6
      src/ldso/dynlink.c
  3. 17 0
      src/thread/__tls_get_addr.c

+ 0 - 5
src/env/__init_tls.c

@@ -53,11 +53,6 @@ void *__copy_tls(unsigned char *mem)
 	return td;
 }
 
-void *__tls_get_addr(size_t *v)
-{
-	return (char *)__pthread_self()->dtv[1]+v[1];
-}
-
 #if ULONG_MAX == 0xffffffff
 typedef Elf32_Phdr Phdr;
 #else

+ 6 - 6
src/ldso/dynlink.c

@@ -1031,17 +1031,15 @@ void *__copy_tls(unsigned char *mem)
 	return td;
 }
 
-void *__tls_get_addr(size_t *v)
+void *__tls_get_new(size_t *v)
 {
 	pthread_t self = __pthread_self();
-	if (v[0]<=(size_t)self->dtv[0])
-		return (char *)self->dtv[v[0]]+v[1];
 
 	/* Block signals to make accessing new TLS async-signal-safe */
 	sigset_t set;
-	pthread_sigmask(SIG_BLOCK, SIGALL_SET, &set);
+	__block_all_sigs(&set);
 	if (v[0]<=(size_t)self->dtv[0]) {
-		pthread_sigmask(SIG_SETMASK, &set, 0);
+		__restore_sigs(&set);
 		return (char *)self->dtv[v[0]]+v[1];
 	}
 
@@ -1074,7 +1072,7 @@ void *__tls_get_addr(size_t *v)
 		memcpy(mem, p->tls_image, p->tls_len);
 		if (p->tls_id == v[0]) break;
 	}
-	pthread_sigmask(SIG_SETMASK, &set, 0);
+	__restore_sigs(&set);
 	return mem + v[1];
 }
 
@@ -1442,6 +1440,8 @@ static int invalid_dso_handle(void *h)
 	return 1;
 }
 
+void *__tls_get_addr(size_t *);
+
 static void *do_dlsym(struct dso *p, const char *s, void *ra)
 {
 	size_t i;

+ 17 - 0
src/thread/__tls_get_addr.c

@@ -0,0 +1,17 @@
+#include <stddef.h>
+#include "pthread_impl.h"
+#include "libc.h"
+
+void *__tls_get_new(size_t *) ATTR_LIBC_VISIBILITY;
+
+void *__tls_get_addr(size_t *v)
+{
+	pthread_t self = __pthread_self();
+#ifdef SHARED
+	if (v[0]<=(size_t)self->dtv[0])
+		return (char *)self->dtv[v[0]]+v[1];
+	return __tls_get_new(v);
+#else
+	return (char *)self->dtv[1]+v[1];
+#endif
+}