summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/env/__init_tls.c5
-rw-r--r--src/ldso/dynlink.c12
-rw-r--r--src/thread/__tls_get_addr.c17
3 files changed, 23 insertions, 11 deletions
diff --git a/src/env/__init_tls.c b/src/env/__init_tls.c
index f7eab8d6..13cf2eea 100644
--- a/src/env/__init_tls.c
+++ b/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
diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c
index 2b6f0c94..bc4f2f6f 100644
--- a/src/ldso/dynlink.c
+++ b/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;
diff --git a/src/thread/__tls_get_addr.c b/src/thread/__tls_get_addr.c
new file mode 100644
index 00000000..28ec7f02
--- /dev/null
+++ b/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
+}