allow global-dynamic on glibc - #181
Conversation
…nd EG into __thread storage)
| || code = 0xd53bd040 | reg; // TODO: hard-coded: mrs reg, tpidr_el0 | ||
| | .long code | ||
| ||# ifdef __FreeBSD__ | ||
| ||# ifndef __MUSL__ |
There was a problem hiding this comment.
May be it's better to change this into #if defined(__FreeBSD__) || defined(something_else)
@ndossche what do you think? You should know this better than me.
Despite of this change, many years ago I tried moving more TSRM data into native __thread TLS.
That time I had troubles with PHP compiled as DSO Apache module.
The size of some TLS table couldn't grow above some limit defined in the main program.
Using "global-dynmic" will lead to worse code. So what is the benefit?
There was a problem hiding this comment.
Despite of this change, many years ago I tried moving more TSRM data into native __thread TLS.
That time I had troubles with PHP compiled as DSO Apache module.
The size of some TLS table couldn't grow above some limit defined in the main program.
Yes, that's glibc's static TLS surplus. Musl doesn't have the concept and therefore (currently, I plan to change this) doesn't set an explicit model. Glibc has the explicit initial-exec optimization for PIC code. Moving EG and CG into __thread storage indeed surpasses the limit which will forces global-dynamic default, resulting in a degradation of the apache module at the benefit of improving performance for all other SAPIs.
For the apache module specifically, I have a --with-tsrm-tls-model flag which package maintainers such as Remi (or myself) can use to still use initial-exec on the apache module. This works because glibc exposes a per-process environment variable GLIBC_TUNABLES that can be set to glibc.rtld.optional_static_tls=8192 to increase the tls surplus. Then the apache module also benefits from saving a tls pointer load every time.
There was a problem hiding this comment.
Long time not heard, hope everything is well.
@ndossche what do you think? You should know this better than me.
The official AArch64 ELF TLS ABI spec leaves the specific layout, and therefore the DTV offset, out of scope:
the details of TLS descriptors are beyond the scope of this specification
It references https://www.fsfla.org/~lxoliva/writeups/TLS/paper-lk2006.pdf for more specific implementation details. This in itself references Ulrich Drepper's document (cite [4]) w.r.t. layout.
On AArch64, all BSD variants seem to use variant 1 as described from Ulrich Drepper's document, they inherited that from a completely different platform: IA64. Variant 1 defines the DTV offset to be 0.
Double-checking common BSD variants:
- FreeBSD
sys/arm64/include/tls.h:TLS_DTV_OFFSETis 0 - NetBSD
sys/sys/tls.h (variant I: void **tcb_dtv; void *tcb_pthread;), and variant I is used on AArch64, i.e. offset 0 - OpenBSD
include/tib.h, sys/arch/arm64/include/tcb.h, again variant 1,{ void *tib_dtv; void *tib_thread; }
This appears to be right.
MUSL is the exception where DTV is at offset -8.
But that said, it is safer to explicitly list the platforms rather than stating "everything not MUSL". I prefer explicitness.
|
@henderkes |
Not yet. I'll have to look those up with my later musl plans, but for now I'm not changing anything about the branches. Glibc and FreeBSD and Musl all stay the same here, the only difference is that glibc global-dynamic now doesn't fail because the branch wasn't handled. I just assumed it would work the same as on FreeBSD and it indeed did. |
|
Generally, the only differences here are having a constant offset (local-exec, initial-offset) or having to go through the DTV (global-dynamic) with the size details dealt with downstream, the only thing we really care about is what offset the DTV is from the thread pointer. That's +0 on freebsd/glibc and -8 on musl, trusting the current implementation. Which means we can actually fold quite a lot of code paths here. Edit: changed +8 to -8. That's for a later rework though, I'll get to it because I want to teach the JIT to get the address of a thread local without loading a pointer. |
|
According to Google FreeBSD, GLIB and MUSL use similar TLS layout. https://www.google.com/search?q=glibc+aarch64+thread+control+block+and+thread+local+storage+layout I suppose the current https://www.google.com/search?q=musl+struct+pthread I have no idea why we have to use Anyway, this patch won't break anything, so I'm merging it. |
(planned downstream work of moving CG and EG into __thread storage)