Issue 9476 - Support native TLS on Mac OS X
Summary: Support native TLS on Mac OS X
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All Mac OS X
: P2 enhancement
Assignee: No Owner
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-02-08 00:41 UTC by Jacob Carlborg
Modified: 2019-05-15 11:27 UTC (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Jacob Carlborg 2013-02-08 00:41:38 UTC
Since Mac OS X Lion (10.7) and later native TLS is available. This is basically needed if we want to support dynamic libraries on Mac OS X. Otherwise we would need to do parts of what the dynamic linker is doing in druntime. Both DMD and druntime need to be changed for this.

We need to be a bit careful when implementing this since this change will make DMD require Mac OS X 10.7 instead of currently 10.6. There's also always the option of doing what the dynamic linker is doing for TLS in druntime to keep the support for Mac OS X 10.6.

I can add a bit more implementation details later.
Comment 1 Martin Nowak 2013-03-07 03:43:50 UTC
Can you provide any links or information?
After searching around quite a lot I get the impression there is no native TLS support in OSX. The only thing I could find are related to __emutls_get_address calls created by certain clang/gcc version. At least the newest gcc (build 5658) doesn't support __thread out of the box.
Comment 2 Jacob Carlborg 2013-03-07 04:34:32 UTC
Right, I forgot about this. This is some information for a couple of post I wrote in the newgroups:

Original code: http://pastebin.com/UKb6etWD

Disassembly with TLS: http://pastebin.com/nkdnE9w6
Disassembly without TLS: http://pastebin.com/vuvEBWWH

Object dump with TLS: http://pastebin.com/PqpPw56a
Object dump without TLS: http://pastebin.com/ki6atzEm

The source code for the dynamic linker on Mac OS X 10.7+ with the TLS handling:

http://opensource.apple.com/source/dyld/dyld-210.2.3/src/threadLocalHelpers.s 
http://opensource.apple.com/source/dyld/dyld-210.2.3/src/threadLocalVariables.c 

A description of what's basically happening in the source code above:

"I've done some investigation. Currently DMD inserts a call to the __tls_get_addr function when accessing a TLS variable. This is implemented in druntime.

In Mac OS X 10.7 it works similar but instead of inserting a call to __tls_get_addr there's a struct looking like this (written in D) :

struct TLVDescriptor
{
    void* function (TLVDescriptor*) thunk;
    size_t key;
    size_t offset;
}

The dynamic linker will iterate all loaded images and extract the section containing the TLS data. I guess this section consists of a list of TLVDescriptor*. The dynamic linker will set the "thunk" to a function "tlv_get_addrs", implemented in assembly in the dynamic linker. It will set the key to a key created by "pthread_key_create". It will also map the image with this key. This key is same for all TLVDescriptor of a given image.

Instead of calling "__tls_get_addr" I think that the compiler will need to call the thunk passing in the TLVDescriptor itself to the thunk.

The "tlv_get_addrs" function will then extract the key and from that key it can get the image the address belongs to.

Does that make any sens? Is that something the DMD could do, that is call the thunk instead of "__tls_get_addr".?"
Comment 3 Martin Nowak 2013-03-07 07:05:20 UTC
(In reply to comment #2)
> Right, I forgot about this. This is some information for a couple of post I
> wrote in the newgroups:
> 
> Original code: http://pastebin.com/UKb6etWD
> 
> Disassembly with TLS: http://pastebin.com/nkdnE9w6
> Disassembly without TLS: http://pastebin.com/vuvEBWWH
> 

How did you compile the code? Did you have to use a certain compiler and version?
Comment 4 Jacob Carlborg 2013-03-07 08:23:27 UTC
(In reply to comment #3)

> How did you compile the code? Did you have to use a certain compiler and
> version?

$ clang --version
Apple clang version 4.1 (tags/Apple/clang-421.11.66) (based on LLVM 3.1svn)
Target: x86_64-apple-darwin12.2.0
Thread model: posix

Mac OS X 10.8.2
Xcode Version 4.6 (4H127)

The exact version used by Xcode would is:

$ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang --version
Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
Target: x86_64-apple-darwin12.2.0
Thread model: posix

But they give the same code. This is compiled for 32bit, if you haven't already figured that out.
Comment 5 Jacob Carlborg 2013-03-07 08:26:39 UTC
GCC shipped with the same version of Xcode cannot build the code:

$ gcc --version
i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00)
Copyright (C) 2007 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

I guess Apple doesn't really care about GCC anymore.
Comment 6 Jacob Carlborg 2013-03-07 08:33:49 UTC
This thread might be of interest as well. It's from the Clang mailing list:

http://lists.cs.uiuc.edu/pipermail/cfe-dev/2012-November/025571.html
Comment 7 Martin Nowak 2013-03-11 11:25:13 UTC
The needed functionality appeared in dyld-195.5 and ld64-123.2.
http://www.opensource.apple.com/source/dyld/dyld-195.5/src/threadLocalHelpers.s
http://www.opensource.apple.com/source/dyld/dyld-195.5/src/threadLocalVariables.c
If older linkers ignore the new sections and flags we probably might create objects using the new TLV mechanism and do the dyld part in druntime for older versions but I don't have time for this right now.

NB:
http://forum.dlang.org/thread/F2166CBA-4F77-49F7-9949-9F3666C12840@me.com
Comment 8 Jacob Carlborg 2013-03-17 08:22:54 UTC
(In reply to comment #7)
> The needed functionality appeared in dyld-195.5 and ld64-123.2.
> http://www.opensource.apple.com/source/dyld/dyld-195.5/src/threadLocalHelpers.s
> http://www.opensource.apple.com/source/dyld/dyld-195.5/src/threadLocalVariables.c
> If older linkers ignore the new sections and flags we probably might create
> objects using the new TLV mechanism and do the dyld part in druntime for older
> versions but I don't have time for this right now.

I was thinking the same thing, although Walter doesn't seem particular happy about the idea. On the other hand, I don't think he wants to drop the support for 10.6 yet.

I think it should be fairly easy to port threadLocalVariables.c to D and include it in druntime. Although to would probably not be allowed to to license issues. What are our options here?
Comment 9 Jacob Carlborg 2013-03-19 12:17:30 UTC
I could probably try implementing the code for druntime. But I don't think I have enough knowledge about DMD and TLS to make the necessary changes to DMD.
Comment 10 Kevin L 2014-11-03 02:04:25 UTC
Rather than remove it, could the existing non-native OSX TLS model be made available via compile command-line argument for all platforms?  Something like "-non-native-tls"?

I am writing a bare-metal kernel (https://github.com/klamonte/cycle) in D (2.066.1-rc2) and am working on TLS support.  It is made more difficult by compiling on Linux DMD with the much more complex sections_linux.d DSO model.

I have gotten ModuleInfo to work without too much hassle using a small bit of linker script:

    .minfo : {
	start_minfo = . ;
	KEEP (*(SORT_NONE(.minfo)))
	end_minfo = . ;
    }

(This BTW continues to work with --gc-sections.)

I'd really like to be able to do similar for TLS, basically do the method described in the Dr Dobbs article for OSX TLS support but on my Linux system.  I'll also need TLS in order for exceptions to work later on.
Comment 11 John Colvin 2014-11-11 14:31:45 UTC
I think the time has come that 10.6 support could be dropped, no? It's no longer supported by Apple.
Comment 12 Jacob Carlborg 2014-11-11 15:39:29 UTC
(In reply to John Colvin from comment #11)
> I think the time has come that 10.6 support could be dropped, no? It's no
> longer supported by Apple.

Fine by me.
Comment 13 John Colvin 2014-11-14 10:21:37 UTC
Some related chatter from ghc:
https://ghc.haskell.org/trac/ghc/ticket/7602
Comment 15 Jacob Carlborg 2019-05-15 11:27:38 UTC
This has been implemented: https://github.com/dlang/dmd/commit/58b204f4957261ef7385c2f17a1e57fbd04169e5.