Skip to content

Commit 6717827

Browse files
committed
[libc++] Implement library support for MCF thread model
This commit allows building libcxx and libcxxabi with cmake -DLIBCXX_HAS_MCF_THREAD_API=ON \ -DLIBCXXABI_HAS_MCF_THREAD_API=ON \ ... This commit adds a new macro, `_LIBCPP_HAS_THREAD_API_MCF`, to indicate that the libraries have been built with MCF thread model. These functions, and member functions of these classes, are implemented directly in libmcfgthread. The list is exhaustive. If someone wants to implement more, such as `std::counting_semaphore` and `std::timed_mutex`, please let me know: * `__cxa_guard_acquire()` * `__cxa_guard_release()` * `__cxa_guard_abort()` * `std::mutex` * `std::call_once()` * `std::recursive_mutex` * `std::condition_variable` * `std::thread` * `std::this_thread::get_id()` * `std::this_thread::sleep_for()` * `std::this_thread::yield()` Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=f036d759ecee538555fa8c6b11963e4033732463 Reference: https://github.com/lhmouse/mcfgthread/wiki/How-the-MCF-thread-model-works Signed-off-by: LIU Hao <[email protected]>
1 parent 6d98f11 commit 6717827

File tree

11 files changed

+126
-11
lines changed

11 files changed

+126
-11
lines changed

libcxx/CMakeLists.txt

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ endif()
295295
option(LIBCXX_HAS_MUSL_LIBC "Build libc++ with support for the Musl C library" OFF)
296296
option(LIBCXX_HAS_PTHREAD_API "Ignore auto-detection and force use of pthread API" OFF)
297297
option(LIBCXX_HAS_WIN32_THREAD_API "Ignore auto-detection and force use of win32 thread API" OFF)
298+
option(LIBCXX_HAS_MCF_THREAD_API "Ignore auto-detection and force use of mcfgthread API" OFF)
298299
option(LIBCXX_HAS_EXTERNAL_THREAD_API
299300
"Build libc++ with an externalized threading API.
300301
This option may only be set to ON when LIBCXX_ENABLE_THREADS=ON." OFF)
@@ -342,7 +343,10 @@ if(NOT LIBCXX_ENABLE_THREADS)
342343
message(FATAL_ERROR "LIBCXX_HAS_WIN32_THREAD_API can only be set to ON"
343344
" when LIBCXX_ENABLE_THREADS is also set to ON.")
344345
endif()
345-
346+
if (LIBCXX_HAS_MCF_THREAD_API)
347+
message(FATAL_ERROR "LIBCXX_HAS_MCF_THREAD_API can only be set to ON"
348+
" when LIBCXX_ENABLE_THREADS is also set to ON.")
349+
endif()
346350
endif()
347351

348352
if (LIBCXX_HAS_EXTERNAL_THREAD_API)
@@ -356,6 +360,11 @@ if (LIBCXX_HAS_EXTERNAL_THREAD_API)
356360
" and LIBCXX_HAS_WIN32_THREAD_API cannot be both"
357361
" set to ON at the same time.")
358362
endif()
363+
if (LIBCXX_HAS_MCF_THREAD_API)
364+
message(FATAL_ERROR "The options LIBCXX_HAS_EXTERNAL_THREAD_API"
365+
" and LIBCXX_HAS_MCF_THREAD_API cannot be both"
366+
" set to ON at the same time.")
367+
endif()
359368
endif()
360369

361370
if (LIBCXX_HAS_PTHREAD_API)
@@ -364,6 +373,19 @@ if (LIBCXX_HAS_PTHREAD_API)
364373
" and LIBCXX_HAS_WIN32_THREAD_API cannot be both"
365374
" set to ON at the same time.")
366375
endif()
376+
if (LIBCXX_HAS_MCF_THREAD_API)
377+
message(FATAL_ERROR "The options LIBCXX_HAS_PTHREAD_API"
378+
" and LIBCXX_HAS_MCF_THREAD_API cannot be both"
379+
" set to ON at the same time.")
380+
endif()
381+
endif()
382+
383+
if (LIBCXX_HAS_WIN32_THREAD_API)
384+
if (LIBCXX_HAS_MCF_THREAD_API)
385+
message(FATAL_ERROR "The options LIBCXX_HAS_WIN32_THREAD_API"
386+
" and LIBCXX_HAS_MCF_THREAD_API cannot be both"
387+
" set to ON at the same time.")
388+
endif()
367389
endif()
368390

369391
if (NOT LIBCXX_ENABLE_RTTI AND LIBCXX_ENABLE_EXCEPTIONS)
@@ -754,6 +776,7 @@ endif()
754776
config_define(${LIBCXX_HAS_PTHREAD_API} _LIBCPP_HAS_THREAD_API_PTHREAD)
755777
config_define(${LIBCXX_HAS_EXTERNAL_THREAD_API} _LIBCPP_HAS_THREAD_API_EXTERNAL)
756778
config_define(${LIBCXX_HAS_WIN32_THREAD_API} _LIBCPP_HAS_THREAD_API_WIN32)
779+
config_define(${LIBCXX_HAS_MCF_THREAD_API} _LIBCPP_HAS_THREAD_API_MCF)
757780
config_define(${LIBCXX_HAS_MUSL_LIBC} _LIBCPP_HAS_MUSL_LIBC)
758781
config_define_if(LIBCXX_NO_VCRUNTIME _LIBCPP_NO_VCRUNTIME)
759782
config_define(${LIBCXX_ENABLE_FILESYSTEM} _LIBCPP_HAS_FILESYSTEM)

libcxx/docs/DesignDocs/ThreadingSupportAPI.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,7 @@ Threading Configuration Macros
6565
**_LIBCPP_HAS_THREAD_API_WIN32**
6666
This macro is defined when libc++ should use Win32 threads to implement the
6767
internal threading API.
68+
69+
**_LIBCPP_HAS_THREAD_API_MCF**
70+
This macro is defined when libc++ should use the mcfgthread library to
71+
implement the internal threading API.

libcxx/include/__config

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -809,6 +809,7 @@ typedef __char32_t char32_t;
809809
# if _LIBCPP_HAS_THREADS && \
810810
!_LIBCPP_HAS_THREAD_API_PTHREAD && \
811811
!_LIBCPP_HAS_THREAD_API_WIN32 && \
812+
!_LIBCPP_HAS_THREAD_API_MCF && \
812813
!_LIBCPP_HAS_THREAD_API_EXTERNAL
813814

814815
# if defined(__FreeBSD__) || \
@@ -882,7 +883,7 @@ typedef __char32_t char32_t;
882883
// clang-format off
883884
# if (_LIBCPP_HAS_THREAD_API_PTHREAD && defined(__GLIBC__)) || \
884885
(_LIBCPP_HAS_THREAD_API_C11 && defined(__Fuchsia__)) || \
885-
_LIBCPP_HAS_THREAD_API_WIN32
886+
_LIBCPP_HAS_THREAD_API_WIN32 || _LIBCPP_HAS_THREAD_API_MCF
886887
// clang-format on
887888
# define _LIBCPP_HAS_TRIVIAL_MUTEX_DESTRUCTION 1
888889
# else
@@ -897,7 +898,8 @@ typedef __char32_t char32_t;
897898
//
898899
// TODO(EricWF): This is potentially true for some pthread implementations
899900
// as well.
900-
# if (_LIBCPP_HAS_THREAD_API_C11 && defined(__Fuchsia__)) || _LIBCPP_HAS_THREAD_API_WIN32
901+
# if (_LIBCPP_HAS_THREAD_API_C11 && defined(__Fuchsia__)) || \
902+
_LIBCPP_HAS_THREAD_API_WIN32 || _LIBCPP_HAS_THREAD_API_MCF
901903
# define _LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION 1
902904
# else
903905
# define _LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION 0

libcxx/include/__config_site.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#cmakedefine01 _LIBCPP_HAS_THREAD_API_PTHREAD
2121
#cmakedefine01 _LIBCPP_HAS_THREAD_API_EXTERNAL
2222
#cmakedefine01 _LIBCPP_HAS_THREAD_API_WIN32
23+
#cmakedefine01 _LIBCPP_HAS_THREAD_API_MCF
2324
#define _LIBCPP_HAS_THREAD_API_C11 0 // FIXME: Is this guarding dead code?
2425
#cmakedefine _LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS
2526
#cmakedefine01 _LIBCPP_HAS_VENDOR_AVAILABILITY_ANNOTATIONS

libcxx/include/__thread/support.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ _LIBCPP_END_NAMESPACE_STD
114114
# include <__thread/support/c11.h>
115115
# elif _LIBCPP_HAS_THREAD_API_WIN32
116116
# include <__thread/support/windows.h>
117+
# elif defined(_LIBCPP_HAS_THREAD_API_MCF)
118+
# include <mcfgthread/libcxx.h>
117119
# else
118120
# error "No threading API was selected"
119121
# endif

libcxx/src/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ if(WIN32)
105105
support/win32/support.cpp
106106
)
107107

108-
if (NOT LIBCXX_HAS_PTHREAD_API)
108+
if (LIBCXX_HAS_WIN32_THREAD_API)
109109
list(APPEND LIBCXX_SOURCES
110110
support/win32/thread_win32.cpp
111111
)

libcxxabi/CMakeLists.txt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ option(LIBCXXABI_USE_COMPILER_RT "Use compiler-rt instead of libgcc" OFF)
5656
option(LIBCXXABI_ENABLE_THREADS "Build with threads enabled" ON)
5757
option(LIBCXXABI_HAS_PTHREAD_API "Ignore auto-detection and force use of pthread API" OFF)
5858
option(LIBCXXABI_HAS_WIN32_THREAD_API "Ignore auto-detection and force use of win32 thread API" OFF)
59+
option(LIBCXXABI_HAS_MCF_THREAD_API "Ignore auto-detection and force use of mcfgthread API" OFF)
5960
option(LIBCXXABI_HAS_EXTERNAL_THREAD_API
6061
"Build libc++abi with an externalized threading API.
6162
This option may only be set to ON when LIBCXXABI_ENABLE_THREADS=ON." OFF)
@@ -318,6 +319,11 @@ if (NOT LIBCXXABI_ENABLE_THREADS)
318319
" be set to ON when LIBCXXABI_ENABLE_THREADS"
319320
" is also set to ON.")
320321
endif()
322+
if (LIBCXXABI_HAS_MCF_THREAD_API)
323+
message(FATAL_ERROR "LIBCXXABI_HAS_MCF_THREAD_API can only"
324+
" be set to ON when LIBCXXABI_ENABLE_THREADS"
325+
" is also set to ON.")
326+
endif()
321327
add_definitions(-D_LIBCXXABI_HAS_NO_THREADS)
322328
endif()
323329

@@ -332,6 +338,11 @@ if (LIBCXXABI_HAS_EXTERNAL_THREAD_API)
332338
" and LIBCXXABI_HAS_WIN32_THREAD_API cannot be both"
333339
" set to ON at the same time.")
334340
endif()
341+
if (LIBCXXABI_HAS_MCF_THREAD_API)
342+
message(FATAL_ERROR "The options LIBCXXABI_HAS_EXTERNAL_THREAD_API"
343+
" and LIBCXXABI_HAS_MCF_THREAD_API cannot be both"
344+
" set to ON at the same time.")
345+
endif()
335346
endif()
336347

337348
if (LIBCXXABI_HAS_PTHREAD_API)
@@ -340,6 +351,19 @@ if (LIBCXXABI_HAS_PTHREAD_API)
340351
"and LIBCXXABI_HAS_WIN32_THREAD_API cannot be both"
341352
"set to ON at the same time.")
342353
endif()
354+
if (LIBCXXABI_HAS_MCF_THREAD_API)
355+
message(FATAL_ERROR "The options LIBCXXABI_HAS_PTHREAD_API"
356+
"and LIBCXXABI_HAS_MCF_THREAD_API cannot be both"
357+
"set to ON at the same time.")
358+
endif()
359+
endif()
360+
361+
if (LIBCXXABI_HAS_WIN32_THREAD_API)
362+
if (LIBCXXABI_HAS_MCF_THREAD_API)
363+
message(FATAL_ERROR "The options LIBCXXABI_HAS_WIN32_THREAD_API"
364+
"and LIBCXXABI_HAS_MCF_THREAD_API cannot be both"
365+
"set to ON at the same time.")
366+
endif()
343367
endif()
344368

345369
if (LLVM_ENABLE_MODULES)
@@ -375,6 +399,10 @@ if (LIBCXXABI_HAS_EXTERNAL_THREAD_API)
375399
add_definitions(-D_LIBCPP_HAS_THREAD_API_EXTERNAL)
376400
endif()
377401

402+
if (LIBCXXABI_HAS_MCF_THREAD_API)
403+
add_definitions(-D_LIBCPP_HAS_THREAD_API_MCF)
404+
endif()
405+
378406
if (MSVC)
379407
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
380408
endif()

libcxxabi/src/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ if (ANDROID AND ANDROID_PLATFORM_LEVEL LESS 21)
9090
list(APPEND LIBCXXABI_LIBRARIES android_support)
9191
endif()
9292

93+
if (LIBCXXABI_HAS_MCF_THREAD_API)
94+
list(APPEND LIBCXXABI_LIBRARIES mcfgthread ntdll)
95+
endif()
96+
9397
# Setup flags.
9498
if (CXX_SUPPORTS_NOSTDLIBXX_FLAG)
9599
add_link_flags_if_supported(-nostdlib++)

libcxxabi/src/cxa_guard_impl.h

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@
6868
# if defined(__ELF__) && defined(_LIBCXXABI_LINK_PTHREAD_LIB)
6969
# pragma comment(lib, "pthread")
7070
# endif
71+
# if _LIBCPP_HAS_THREAD_API_MCF
72+
# include <mcfgthread/cxa.h>
73+
# endif
7174
#endif
7275

7376
#if defined(__clang__)
@@ -608,6 +611,38 @@ struct GuardObject {
608611
}
609612
};
610613

614+
//===----------------------------------------------------------------------===//
615+
// GuardObject for MCF
616+
//===----------------------------------------------------------------------===//
617+
618+
/// Forwards everything to libmcfgthread
619+
struct GuardObject_MCF;
620+
#if _LIBCPP_HAS_THREAD_API_MCF
621+
struct GuardObject_MCF {
622+
GuardObject_MCF() = delete;
623+
GuardObject_MCF(GuardObject_MCF const&) = delete;
624+
GuardObject_MCF& operator=(GuardObject_MCF const&) = delete;
625+
626+
private:
627+
int64_t* guard_ptr;
628+
629+
public:
630+
explicit GuardObject_MCF(uint64_t* raw_guard_object)
631+
: guard_ptr(reinterpret_cast<int64_t*>(raw_guard_object)) { }
632+
633+
/// Implements __cxa_guard_acquire.
634+
AcquireResult cxa_guard_acquire() {
635+
return static_cast<AcquireResult>(__MCF_cxa_guard_acquire(guard_ptr));
636+
}
637+
638+
/// Implements __cxa_guard_release.
639+
void cxa_guard_release() { __MCF_cxa_guard_release(guard_ptr); }
640+
641+
/// Implements __cxa_guard_abort.
642+
void cxa_guard_abort() { __MCF_cxa_guard_abort(guard_ptr); }
643+
};
644+
#endif
645+
611646
//===----------------------------------------------------------------------===//
612647
// Convenience Classes
613648
//===----------------------------------------------------------------------===//
@@ -628,6 +663,9 @@ template <void (*Wait)(int*, int) = PlatformFutexWait, void (*Wake)(int*) = Plat
628663
uint32_t (*GetThreadIDArg)() = PlatformThreadID>
629664
using FutexGuard = GuardObject<InitByteFutex<Wait, Wake, GetThreadIDArg>>;
630665

666+
/// MCFGuard - Forwards everything to libmcfgthread
667+
using MCFGuard = GuardObject_MCF;
668+
631669
//===----------------------------------------------------------------------===//
632670
//
633671
//===----------------------------------------------------------------------===//
@@ -639,7 +677,7 @@ struct GlobalStatic {
639677
template <class T>
640678
_LIBCPP_CONSTINIT T GlobalStatic<T>::instance = {};
641679

642-
enum class Implementation { NoThreads, GlobalMutex, Futex };
680+
enum class Implementation { NoThreads, GlobalMutex, Futex, MCF };
643681

644682
template <Implementation Impl>
645683
struct SelectImplementation;
@@ -660,13 +698,20 @@ struct SelectImplementation<Implementation::Futex> {
660698
using type = FutexGuard<PlatformFutexWait, PlatformFutexWake, PlatformThreadID>;
661699
};
662700

701+
template <>
702+
struct SelectImplementation<Implementation::MCF> {
703+
using type = MCFGuard;
704+
};
705+
663706
// TODO(EricWF): We should prefer the futex implementation when available. But
664707
// it should be done in a separate step from adding the implementation.
665708
constexpr Implementation CurrentImplementation =
666709
#if defined(_LIBCXXABI_HAS_NO_THREADS)
667710
Implementation::NoThreads;
668711
#elif defined(_LIBCXXABI_USE_FUTEX)
669712
Implementation::Futex;
713+
#elif _LIBCPP_HAS_THREAD_API_MCF
714+
Implementation::MCF;
670715
#else
671716
Implementation::GlobalMutex;
672717
#endif

libcxxabi/src/cxa_thread_atexit.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,12 @@
1010
#include "cxxabi.h"
1111
#include <__thread/support.h>
1212
#ifndef _LIBCXXABI_HAS_NO_THREADS
13-
#if defined(__ELF__) && defined(_LIBCXXABI_LINK_PTHREAD_LIB)
14-
#pragma comment(lib, "pthread")
15-
#endif
13+
# if defined(__ELF__) && defined(_LIBCXXABI_LINK_PTHREAD_LIB)
14+
# pragma comment(lib, "pthread")
15+
# endif
16+
# if _LIBCPP_HAS_THREAD_API_MCF
17+
# include <mcfgthread/cxa.h>
18+
# endif
1619
#endif
1720

1821
#include <stdlib.h>
@@ -22,14 +25,14 @@ namespace __cxxabiv1 {
2225
using Dtor = void(*)(void*);
2326

2427
extern "C"
25-
#ifndef HAVE___CXA_THREAD_ATEXIT_IMPL
28+
#if !defined(HAVE___CXA_THREAD_ATEXIT_IMPL)
2629
// A weak symbol is used to detect this function's presence in the C library
2730
// at runtime, even if libc++ is built against an older libc
2831
_LIBCXXABI_WEAK
2932
#endif
3033
int __cxa_thread_atexit_impl(Dtor, void*, void*);
3134

32-
#ifndef HAVE___CXA_THREAD_ATEXIT_IMPL
35+
#if !(_LIBCPP_HAS_THREAD_API_MCF || defined(HAVE___CXA_THREAD_ATEXIT_IMPL))
3336

3437
namespace {
3538
// This implementation is used if the C library does not provide
@@ -109,7 +112,9 @@ namespace {
109112
extern "C" {
110113

111114
_LIBCXXABI_FUNC_VIS int __cxa_thread_atexit(Dtor dtor, void* obj, void* dso_symbol) throw() {
112-
#ifdef HAVE___CXA_THREAD_ATEXIT_IMPL
115+
#if _LIBCPP_HAS_THREAD_API_MCF
116+
return __MCF_cxa_thread_atexit(dtor, obj, dso_symbol);
117+
#elif defined(HAVE___CXA_THREAD_ATEXIT_IMPL)
113118
return __cxa_thread_atexit_impl(dtor, obj, dso_symbol);
114119
#else
115120
if (__cxa_thread_atexit_impl) {

llvm/utils/gn/secondary/libcxx/include/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ if (current_toolchain == default_toolchain) {
2626
"_LIBCPP_HAS_THREAD_API_PTHREAD=",
2727
"_LIBCPP_HAS_THREAD_API_EXTERNAL=",
2828
"_LIBCPP_HAS_THREAD_API_WIN32=",
29+
"_LIBCPP_HAS_THREAD_API_MCF=",
2930
"_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS=",
3031
"_LIBCPP_HAS_VENDOR_AVAILABILITY_ANNOTATIONS=",
3132
"_LIBCPP_NO_VCRUNTIME=",

0 commit comments

Comments
 (0)