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).
This commit is contained in:
parent
4e0b4a5de7
commit
5ba238e1e4
3 changed files with 23 additions and 11 deletions
5
src/env/__init_tls.c
vendored
5
src/env/__init_tls.c
vendored
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
src/thread/__tls_get_addr.c
Normal file
17
src/thread/__tls_get_addr.c
Normal file
|
|
@ -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
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue