summaryrefslogtreecommitdiff
path: root/src/env/__reset_tls.c
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2018-10-12 00:30:34 -0400
committerRich Felker <dalias@aerifal.cx>2018-10-12 00:39:56 -0400
commitb6d701a47504e5ef9c6a19b2f6a703c72cb9e8ac (patch)
tree861aaaf569834e7ce9ec03c879f53955d15b73e7 /src/env/__reset_tls.c
parent09a805a62307307230a31125425d0c2b0b6f332e (diff)
downloadmusl-b6d701a47504e5ef9c6a19b2f6a703c72cb9e8ac.tar.gz
combine arch ABI's DTP_OFFSET into DTV pointers
as explained in commit 6ba5517a460c6c438f64d69464fdfc3269a4c91a, some archs use an offset (typicaly -0x8000) with their DTPOFF relocations, which __tls_get_addr needs to invert. on affected archs, which lack direct support for large immediates, this can cost multiple extra instructions in the hot path. instead, incorporate the DTP_OFFSET into the DTV entries. this means they are no longer valid pointers, so store them as an array of uintptr_t rather than void *; this also makes it easier to access slot 0 as a valid slot count. commit e75b16cf93ebbc1ce758d3ea6b2923e8b2457c68 left behind cruft in two places, __reset_tls and __tls_get_new, from back when it was possible to have uninitialized gap slots indicated by a null pointer in the DTV. since the concept of null pointer is no longer meaningful with an offset applied, remove this cruft. presently there are no archs with both TLSDESC and nonzero DTP_OFFSET, but the dynamic TLSDESC relocation code is also updated to apply an inverted offset to its offset field, so that the offset DTV would not impose a runtime cost in TLSDESC resolver functions.
Diffstat (limited to 'src/env/__reset_tls.c')
-rw-r--r--src/env/__reset_tls.c9
1 files changed, 4 insertions, 5 deletions
diff --git a/src/env/__reset_tls.c b/src/env/__reset_tls.c
index 677e57f5..15685bc6 100644
--- a/src/env/__reset_tls.c
+++ b/src/env/__reset_tls.c
@@ -6,11 +6,10 @@ void __reset_tls()
{
pthread_t self = __pthread_self();
struct tls_module *p;
- size_t i, n = (size_t)self->dtv[0];
+ size_t i, n = self->dtv[0];
if (n) for (p=libc.tls_head, i=1; i<=n; i++, p=p->next) {
- if (!self->dtv[i]) continue;
- memcpy(self->dtv[i], p->image, p->len);
- memset((char *)self->dtv[i]+p->len, 0,
- p->size - p->len);
+ char *mem = (char *)(self->dtv[i] - DTP_OFFSET);
+ memcpy(mem, p->image, p->len);
+ memset(mem+p->len, 0, p->size - p->len);
}
}