Accessing TLS variable defined in DSO with static tls model from another DSO with dynamic tls model

Ho, Lennox lennox.ho@intel.com
Fri May 28 18:02:54 GMT 2021


> You need to pass -ftls-model=initial-exec when compiling libtls_import.so, not
> the exporting library. I am a bit surprised you've decided to do that the other
> way around :)

Ahh ok so it does appear that I really misunderstood how static TLS works :/.

My assumption has been that since (static) TLS variables are placed in the static TLS segment, at a constant offset (to the left) from the thread pointer (as shown here https://th.bing.com/th/id/R92210a8cb7df88cb1b9586ce73d8da90?rik=FX6vqTs2uG%2brzw&pid=ImgRaw), 
that initial-exec/local-exec is an imperative on the TLS data itself, not on the act of *accessing* said data.

While tagging the DSO that accesses the TLS data (libtls_export.so) with DF_STATIC_TLS will do the trick (libtls_export.so must be loaded before libtls_import.so - which must be loaded before main() - and so the TLS in libtls_export.so can be placed in a static TLS section),
surely tagging the export DSO (libtls_export.so) with DF_STATIC_TLS instead would be more natural?
My understanding is that the dynamic loader will have the opportunity to fixup the offsets in any future DSO that is loaded.

Do you mind elaborating why DF_STATIC_TLS is placed on the client/import DSO and not the export DSO?
Is there something that I'm still missing?

-------------------

To offer some additional context, I have an unfair reader-writer mutex (unfair in that readers are heavily favoured) implementation that uses TLS variables to indicate whether a thread is currently "read-locking".
There are a few other bit and pieces required to make this work, but the advantage of this approach is we completely eliminate cache contention (typical spin-locks have the problem of threads trying to out invalidate each other's cache!) for readers.

Now, the way I'm deploying this TLS variable is by exporting it from a "core" DSO that I know will never be dlopened - it will always be loaded before main.
Code from other DSOs - which may be dlopened at arbitrary points - need to use this TLS variable to perform "read-locking".
I would like to avoid the cost of __tls_get_addr, but at the same time I don't want to force client DSOs to build with -ftls-model=initial-exec (that could prevent them from being dlopened).
I would also like to avoid retrieving this TLS variable through a function call. It needs to be:

mov %fs:0, rbx
mov <offset patched by loader>, rcx
mov rbx[rcx], rax // rax holds the value of the TLS

Surely this is achievable?

Thanks,
Len


More information about the Gcc-help mailing list