This is an archive of the discontinued LLVM Phabricator instance.

[Support] Access threadIndex via a wrapper function
ClosedPublic

Authored by mstorsjo on Sep 13 2022, 1:22 AM.

Details

Summary

On Unix platforms, this wrapper function is inline, so it should
expand to the same direct access to the thread local variable. On
Windows, it's a non-inline function within Parallel.cpp, allowing
making the thread_local variable static.

Windows Native TLS doesn't support direct access to thread local
variables in a different DLL, and GCC/binutils on Windows occasionally
has problems with non-static thread local variables too.

This fixes mingw dylib builds with native TLS.

Diff Detail

Event Timeline

mstorsjo created this revision.Sep 13 2022, 1:22 AM
Herald added a project: Restricted Project. · View Herald TranscriptSep 13 2022, 1:22 AM
mstorsjo requested review of this revision.Sep 13 2022, 1:22 AM
Herald added a project: Restricted Project. · View Herald TranscriptSep 13 2022, 1:22 AM

I think this looks fine to unblock the MinGW dylib build but I wonder if we could reduce the number of calls to getThreadIndex() by storing the index in the RelocationScanner? Although this would require quite a few changes to the existing interfaces.

A couple of suggestions in response to the comment on D133003 regarding no TLS support.

llvm/include/llvm/Support/Parallel.h
31–40

Perhaps place this block within:

#if LLVM_ENABLE_THREADS
<HERE>
#else
inline unsigned getThreadIndex() { return 0; }
#endif

Which along with the other change, should fix any builds with LLVM_ENABLE_THREADS=0 that do not support TLS.

llvm/lib/Support/Parallel.cpp
21–27

Move this block down to below the #if LLVM_ENABLE_THREADS (line 31) and adjust for the namespaces.

mstorsjo updated this revision to Diff 459763.Sep 13 2022, 8:40 AM

Move all use of the TLS variables into within #if LLVM_ENABLE_THREADS as suggested.

andrewng accepted this revision.Sep 13 2022, 9:52 AM

LGTM, although might want to wait to see what @MaskRay thinks.

This revision is now accepted and ready to land.Sep 13 2022, 9:52 AM
MaskRay accepted this revision.Sep 13 2022, 9:48 PM

Interesting. I did not know this limitation.
lld is identical with the change on Linux x86-64.

Interesting. I did not know this limitation.

It's of course a very subtle area; for "proper" DLL linkage, you'd use dllexport/dllimport, and if you combine dllexport/import with thread_local, then MSVC errors out with this error:

error C2492: 'tlsVar': data with thread storage duration may not have dll interface

Clang gives this error:

error: 'tlsVar' cannot be thread local when declared 'dllexport'

(And the same for dllimport too.) Clang does give these same errors also if using -femulated-tls, even if the linkage technically would work there. GCC doesn't error out on either of them (and the linkage does work out in the end, as it uses emulated TLS - but there's other potential pitfalls wrt TLS across object files there, due to their handling of weak linkage).

However, the mingw dylib build doesn't rely on explicit dllexport/imports, but on implicit autoimports, and then we don't get errors at that level at all, but only at linkage time:

ld.lld: error: unable to automatically import from _ZN4llvm8parallel11threadIndexE with relocation type IMAGE_REL_AMD64_SECREL in liblldELF.a(Relocations.cpp.obj)
This revision was landed with ongoing or failed builds.Sep 13 2022, 11:29 PM
This revision was automatically updated to reflect the committed changes.