Supporting emulated tls

Jacob Carlborg doob at me.com
Mon Mar 19 02:40:25 PDT 2012


On 2012-03-19 09:15, Johannes Pfau wrote:
> Am Sun, 18 Mar 2012 21:57:57 +0100
> schrieb Jacob Carlborg<doob at me.com>:
>
>> On 2012-03-18 12:32, Johannes Pfau wrote:
>>> I thought about supporting emulated tls a little. The GCC emutls.c
>>> implementation currently can't work with the gc, as every TLS
>>> variable is allocated individually and therefore we don't have a
>>> contiguous memory region for the gc. I think these are the possible
>>> solutions:
>>
>> Why not use the native TLS implementation when available and roll our
>> own, like DMD on Mac OS X, when none exists?
>
> That's what we (mostly) do right now. We have 2 issues:
>
> * Our own, emulated TLS support is implemented in GCC. This means it's
>    also used in C, which is great. Also GCC's emulated tls needs
>    absolutely no special features in the runtime linker, compile time
>    linker or language frontends. It's very portable and works with all
>    weird combinations of dynamic libraries, dlopen, etc.
>    But it has one quirk: It doesn't allocate TLS memory in a contiguous
>    way, every tls variable is allocated using malloc. This means we
>    can't pass a range to the GC for the tls variables. So we can't
>    support this emutls in the GC.

Ok, I see.

> * The other issue with native TLS is that using bracketing with
>    __tls_beg and __tls_end has corner cases where it doesn't work. We'd
>    need an alternative to locate the TLS memory addresses and TLS sizes.
>    But there's no standard or public API to do that.

On Mac OS X they are actually not needed. Don't know about other platforms.

>> BTW, I think it would be possible to emulate TLS in a very similar
>> way to how it's implemented natively for ELF.
>>
>
> I don't think it's that easy. For example, how would you assign module
> ids? For native TLS this is partially done by the compile time linker
> (for the main application and libraries that are always loaded), but if
> no native TLS is available, we can't rely on the linker to do that. We
> also need some way to get the current module id in running code.

As I understand it, in the native ELF implementation, assembly is used 
to access the current module id, this is for FreeBSD:

http://people.freebsd.org/~marcel/tls.html

This is how ___tls_get_addr is implemented on FreeBSD ELF i386:

https://bitbucket.org/freebsd/freebsd-head/src/4e8f50fe2f05/libexec/rtld-elf/i386/reloc.c#cl-355

> And how do we get the TLS initialization data? If we placed it into an
> array, like DMD does on OSX, we could use dlsym for dlopened libraries,
> but what about initially loaded libraries?

In the same way it's done in the native implementation. Isn't it 
possible to access all loaded libraries?

> Say you have application 'app', which depends on 'liba' and 'libb'. All
> of these have TLS data. Maybe we could implement something using
> dl_iterate_phdr, but that's a nonstandard extension.

Ok. Mac OS X has this a function called 
"_dyld_register_func_for_add_image", I guess other OS'es don't have a 
corresponding function? In general all this stuff very low level and 
nonstandard.

https://developer.apple.com/library/mac/#documentation/developertools/Reference/MachOReference/Reference/reference.html#jumpTo_53

> Compare that to GCC's emulation, which is probably slow, but 'just
> works' everywhere (except for the GC :-( ).

Yeah, that's a big advantage.

In general I was hoping that the work done by the dynamic loader to 
setup TLS could be moved to druntime.

-- 
/Jacob Carlborg


More information about the D.gnu mailing list