This is an archive of the discontinued LLVM Phabricator instance.

[libc++] Add a bunch of missing inline and _LIBCPP_HIDE_FROM_ABI in __threading_support
ClosedPublic

Authored by ldionne on Dec 16 2021, 2:01 PM.

Details

Summary

The inline keyword is required on those functions because they are defined
in the headers, so we need them to be inline to avoid ODR violations.
While we're at it, slap _LIBCPP_HIDE_FROM_ABI on them because they are
implementation details and we don't want them to be part of our ABI under
any circumstances.

Diff Detail

Event Timeline

ldionne requested review of this revision.Dec 16 2021, 2:01 PM
ldionne created this revision.
Herald added a project: Restricted Project. · View Herald TranscriptDec 16 2021, 2:01 PM
Herald added a reviewer: Restricted Project. · View Herald Transcript
ldionne accepted this revision.Dec 17 2021, 9:02 AM
This revision is now accepted and ready to land.Dec 17 2021, 9:02 AM

Should this have used _LIBCPP_THREAD_ABI_VISIBILITY instead? Won't this break _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL? Also, why is this needed when the forward declarations already specify that the functions are inline?

Should this have used _LIBCPP_THREAD_ABI_VISIBILITY instead? Won't this break _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL? Also, why is this needed when the forward declarations already specify that the functions are inline?

For the Pthread case, using _LIBCPP_THREAD_ABI_VISIBILITY and inline _LIBCPP_HIDE_FROM_ABI is equivalent. However your'e right, this doesn't look necessary to me after all since they are all forward declared above with the correct visibility anyways. I find this code rather confusing and I'm going to refactor it to disentangle the different implementations.

I'm not sure how this change would break _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL though?

DanielMcIntosh-IBM added a comment.EditedJan 10 2022, 10:57 AM

For the Pthread case, using _LIBCPP_THREAD_ABI_VISIBILITY and inline _LIBCPP_HIDE_FROM_ABI is equivalent.

Is it not the case for _LIBCPP_HAS_THREAD_API_C11?

I find this code rather confusing and I'm going to refactor it to disentangle the different implementations.

I do agree that the current situation is rather confusing and should be refactored, or at least better documented. It took way too long for me to figure everything below out, and I still don't know what's going on with _LIBCPP_HAS_THREAD_API_WIN32. This was a significant barrier to implementing your recommendations in D110349#3126010 (which are in the process of getting reviewed downstream in addition to some additional documentation). I've been considering trying to clean things up a bit myself, but there are other pressing issues I need to work on in the short and medium term. Can you add me as a subscriber to all of your changes refactoring __threading_support?

I'm not sure how this change would break _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL though?

According to DesignDocs/ThreadingSupportAPI, _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL "is used to build an external threading library using the <__threading_support>. Specifically it exposes the threading API definitions in <__threading_support> as non-inline definitions meant to be compiled into a library." With this change, the definitions are always inline and hidden from the ABI, so that doesn't work anymore.

In more detail, my understanding of the various macros thus far is as follows (please correct me if I've misunderstood):

The API (i.e. the typedefs and forward declarations __threading_support provides) is determined by which (if any) of the following macros is defined: _LIBCPP_HAS_THREAD_API_EXTERNAL, _LIBCPP_HAS_THREAD_API_PTHREAD, _LIBCPP_HAS_THREAD_API_C11 or none/generic (with _LIBCPP_HAS_THREAD_API_EXTERNAL, __threading_support provides the typedefs and forward declarations indirectly by #including __external_threading). _LIBCPP_HAS_THREAD_API_WIN32 is a bit of an oddball here, and I'm not really sure I understand it yet.

Independent of which API is used, the function definitions can either be provided by __threading_support, or by an external library when _LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL has been defined (Even when _LIBCPP_HAS_THREAD_API_EXTERNAL is the chosen API, if __external_threading provides definitions in addition to typedefs and forward declarations, the function definitions can theoretically still be indirectly provided by __threading_support rather than an external library. However the cmake files forbid this).

With an external thread library, libc++ is detached from the underlying threading support library, allowing the user/vendor to provide one of their choosing. However, this would cause problems testing libc++ since the threading library is provided by the user/vendor, meaning we don't have one to use for testing. To work around this, we can build an external library out of the definitions that __threading_support would normally provide inline. This is done using -DLIBCXX_BUILD_EXTERNAL_THREAD_LIBRARY which builds libcxx/test/support/external_threads.cpp into a library. libcxx/test/support/external_threads.cpp does nothing more than #define _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL and #include <__threading_support>. As explained above, _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL causes __threading_support to provide the definitions as non-inline and with _LIBCPP_FUNC_VIS visibility. This way libc++ can be tested with an external threading library as long as __threading_support has function definitions that use a base thread library (e.g. pthread) that the platform it is getting tested on supports.

If the definitions in __threading_support are always inline and hidden from the ABI, we cannot build libcxx/test/support/external_threads.cpp into a library that is usable as an external threading library.

Ping, since as per my previous comment, I'm pretty sure this change will have broken _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL.

miyuki added a subscriber: miyuki.Feb 10 2022, 4:03 AM

Ping, since as per my previous comment, I'm pretty sure this change will have broken _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL.

Yes, indeed it has.

Ping, since as per my previous comment, I'm pretty sure this change will have broken _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL.

Yes, indeed it has.

Sorry, this went under my radar. I just spun off a patch to revert this. If it passes, I'll cherry-pick onto LLVM 14.