TLS performance overhead and cost on GNU/Linux
david-grs.github.io
david-grs.github.io
AFAICT there's no good reason why TLS access couldn't be just a normal segmented access and nothing more, dynamic loading or no... same as it is in the kernel.
Edit: And it's not like these are big in practice, at least in anything I have installed:
find /lib /usr/lib -type f|grep '\.so$'|xargs -n1 size -A|&grep -E '^.(tdata|tbss)'|awk '{print $2}
says that the absolute biggest is 152 bytes, and most are a lot smaller.x86-style segmentation has essentially nothing to do with TLS apart from the fact that it can be abused to implement it without having to reserve additional useful global registers (as it is implemented on typical RISC platforms).
TLS areas are in general very small because very often only thing that is stored there is pointer to some internally managed per-thread heap allocated struct that is then accessed directly (reasons for this are twofold: it is faster in tight loops and there are platforms that do not support linker-visible TLS).
At the core, percpu variables/sections in the kernel are done exactly the same way as the TLS is implemented in userspace, except with gs instead of fs.
The thing that I'm complaining about is that on top of that, glibc is doing lazy allocation for no apparent (sane) reason.