using emulated-tls on Darwin 8, 9, 10

Please excuse hobbiest-level question.

Darwin 11+ enables thread_local variables using system-level supports.

I have an interest in enabling TLS on darwin < 11 using emulated-tls. This can be enabled with a few modest patches:

Is anyone still running macOS 10.6 or older?

[off topic, apologies]
Yes, there remains a surprising amount of interest in these systems. MacPorts sees very frequent user tickets about them, many tickets lately about thread_local. All versions of clang/llvm run on 10.5+ Intel systems with minor tweaks, including the latest trunk versions, and this enables almost all current opensource software to be used on these systems. Software (like browsers) geared to these systems see downloads in the low thousands per release. I guess people either have a need for these systems for some software version or workflow, or have otherwise workable hardware that as been obsoleted by newer os requirements.

Even PowerPC systems get frequent tickets at MacPorts, and we support them as we can. Some versions of clang will run on PowerPC Macs with workable coverage (in fact the only remaining hole is a persisting issue with a bad address for c++ exceptions being supplied).

[/on topic]

Making the emutls objects in libclang_rt visible to libcxxabi.dylib at runtime has been a hiccup, tho.

It works but seems a shame to hack emutls.c into the libc++abi code when the objects are already sitting there in the executable, but (AFAICT) have the wrong visibility setting to allow use.

At present I don't seem to know enough about the underpinnings to see how to change the visibility settings on the emutls objects from libclang_rt when placed into the executable.

Appreciate any thoughts on this, thanks for your interest, and sorry for the slight divergence above.

Ken (MacPorts dev)

I think I'm possibly getting my head around this...

___emutls_get_address is not hidden in libclang_rt, it's visible:

$ nm /opt/local/libexec/llvm-5.0/lib/clang/5.0.1/lib/darwin/libclang_rt.10.4.a | grep emu
0000000000000000 T ___emutls_get_address

but when that code is incorporated into the executable, the symbol is (by design) not exported beyond the executable, so libc++abi.dylib will never see it.

$ nm 4 | grep emu
0000000100007070 t ___emutls_get_address

and I am actually not sure that it is possible to have executables export symbols for linked libraries to call into. It would be probably bad, even if you could force it.

So perhaps having emutls.c in libclang_rt can never actually work...maybe the emutls.o code needs to exist in a separate dylib (like it does in libgcc).

So putting it into libc++abi.dylib might indeed be the only workable method, assuming each executable would get it's own copy in memory and they wouldn't all collide together.


Can ibc++abi link with libclang_rt to resolve the symbol?

Thanks for the clue, and yes that led me to the answer.

We are building libc++abi with nodefaultlibs . The emutls.o symbols indeed belong right in libc++abi, and I will either compile them in with emutls.c or link them in manually by adding that library.

And then we should be in business, and all systems will have thread_local .

Thanks for the hint.


All that being sorted out, we now have libc++ 7.0.0 and libc++abi built and being used with emulated-tls support on darwin < 11 now. Thanks!

The last bit of this I plan to sort out would be how to tweak the following patch so that __cxa_thread_atexit would be called based on the -femulated-tls flag rather than based on the MacOSXVersion. That way emulated-tls could be used/tested on any OS version. -- Ken

Cool. BTW, what about TLS in C, i.e. "__thread"?

Yes, the various tests I've tried with this pass. I am a hobbyist, not a professional programmer, so it's possible I'm missing some aspect of the TLS coverage or the implementation. The darwin code in llvm generally assumes tlv_atexit for TLS, and I might be overlooking some detail that I haven't as yet discovered.

I wonder if there is any appetite to have darwin support the -femulated-tls flag in general, for testing the subsystems, etc. Right now if you use the flag, you still get tlv_atexit in the end.

I should be able to find a way to test if femulated-tls is set while in the scope of CodeGen/ItaniumCXXABI.cpp and branch on the flag to cxa_thread_atexit -- and if I sort that out, a general implementation would appear workable.