[libcxx-commits] [libcxx] [libc++] Add the thread safety annotations unconditionally (PR #117497)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Mon May 19 00:59:42 PDT 2025
https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/117497
>From b4eaaf797b8902060ac390e166407cc6f0e29eaf Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Sun, 24 Nov 2024 16:44:16 +0100
Subject: [PATCH] [libc++] Add the thread safety annotations unconditionally
---
libcxx/.clang-format | 9 +++-
libcxx/include/__config | 71 ++++++++++++++++++++++-------
libcxx/include/__mutex/lock_guard.h | 10 ++--
libcxx/include/__mutex/mutex.h | 8 ++--
libcxx/include/mutex | 11 ++---
libcxx/include/shared_mutex | 54 +++++++++-------------
6 files changed, 97 insertions(+), 66 deletions(-)
diff --git a/libcxx/.clang-format b/libcxx/.clang-format
index fe2f2ef0119fa..f372ac9619997 100644
--- a/libcxx/.clang-format
+++ b/libcxx/.clang-format
@@ -16,8 +16,11 @@ AllowShortLambdasOnASingleLine: All
AttributeMacros: [
'_ALIGNAS_TYPE',
'_ALIGNAS',
+ '_LIBCPP_ACQUIRE_CAPABILITY',
+ '_LIBCPP_ACQUIRE_SHARED_CAPABILITY',
'_LIBCPP_ALIGNOF',
'_LIBCPP_ALWAYS_INLINE',
+ '_LIBCPP_CAPABILITY',
'_LIBCPP_CONSTEXPR_SINCE_CXX14',
'_LIBCPP_CONSTEXPR_SINCE_CXX17',
'_LIBCPP_CONSTEXPR_SINCE_CXX20',
@@ -41,9 +44,13 @@ AttributeMacros: [
'_LIBCPP_NO_UNIQUE_ADDRESS',
'_LIBCPP_NOALIAS',
'_LIBCPP_OVERRIDABLE_FUNC_VIS',
+ '_LIBCPP_RELEASE_CAPABILITY',
+ '_LIBCPP_REQUIRES_CAPABILITY',
+ '_LIBCPP_SCOPED_LOCKABLE',
'_LIBCPP_STANDALONE_DEBUG',
'_LIBCPP_TEMPLATE_DATA_VIS',
- '_LIBCPP_THREAD_SAFETY_ANNOTATION',
+ '_LIBCPP_TRY_ACQUIRE_CAPABILITY',
+ '_LIBCPP_TRY_ACQUIRE_SHARED_CAPABILITY',
'_LIBCPP_USING_IF_EXISTS',
'_LIBCPP_WEAK',
]
diff --git a/libcxx/include/__config b/libcxx/include/__config
index 57223e4f1db18..6f32dc088933c 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -945,23 +945,6 @@ typedef __char32_t char32_t;
# define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
# endif
-// Work around the attribute handling in clang. When both __declspec and
-// __attribute__ are present, the processing goes awry preventing the definition
-// of the types. In MinGW mode, __declspec evaluates to __attribute__, and thus
-// combining the two does work.
-# if defined(_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS) && defined(__clang__) && \
- __has_attribute(acquire_capability) && !defined(_MSC_VER)
-# define _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS 1
-# else
-# define _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS 0
-# endif
-
-# if _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS
-# define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) __attribute__((x))
-# else
-# define _LIBCPP_THREAD_SAFETY_ANNOTATION(x)
-# endif
-
# if _LIBCPP_STD_VER >= 20
# define _LIBCPP_CONSTINIT constinit
# elif __has_attribute(__require_constant_initialization__)
@@ -1189,6 +1172,60 @@ typedef __char32_t char32_t;
# define _LIBCPP_PREFERRED_NAME(x)
# endif
+# if __has_cpp_attribute(_Clang::__scoped_lockable__)
+# define _LIBCPP_SCOPED_LOCKABLE [[_Clang::__scoped_lockable__]]
+# else
+# define _LIBCPP_SCOPED_LOCKABLE
+# endif
+
+# if __has_cpp_attribute(_Clang::__capability__)
+# define _LIBCPP_CAPABILITY(...) [[_Clang::__capability__(__VA_ARGS__)]]
+# else
+# define _LIBCPP_CAPABILITY(...)
+# endif
+
+# if __has_attribute(__acquire_capability__)
+# define _LIBCPP_ACQUIRE_CAPABILITY(...) __attribute__((__acquire_capability__(__VA_ARGS__)))
+# else
+# define _LIBCPP_ACQUIRE_CAPABILITY(...)
+# endif
+
+# if __has_cpp_attribute(_Clang::__try_acquire_capability__)
+# define _LIBCPP_TRY_ACQUIRE_CAPABILITY(...) [[_Clang::__try_acquire_capability__(__VA_ARGS__)]]
+# else
+# define _LIBCPP_TRY_ACQUIRE_CAPABILITY(...)
+# endif
+
+# if __has_cpp_attribute(_Clang::__acquire_shared_capability__)
+# define _LIBCPP_ACQUIRE_SHARED_CAPABILITY [[_Clang::__acquire_shared_capability__]]
+# else
+# define _LIBCPP_ACQUIRE_SHARED_CAPABILITY
+# endif
+
+# if __has_cpp_attribute(_Clang::__try_acquire_shared_capability__)
+# define _LIBCPP_TRY_ACQUIRE_SHARED_CAPABILITY(...) [[_Clang::__try_acquire_shared_capability__(__VA_ARGS__)]]
+# else
+# define _LIBCPP_TRY_ACQUIRE_SHARED_CAPABILITY(...)
+# endif
+
+# if __has_cpp_attribute(_Clang::__release_capability__)
+# define _LIBCPP_RELEASE_CAPABILITY [[_Clang::__release_capability__]]
+# else
+# define _LIBCPP_RELEASE_CAPABILITY
+# endif
+
+# if __has_cpp_attribute(_Clang::__release_shared_capability__)
+# define _LIBCPP_RELEASE_SHARED_CAPABILITY [[_Clang::__release_shared_capability__]]
+# else
+# define _LIBCPP_RELEASE_SHARED_CAPABILITY
+# endif
+
+# if __has_attribute(__requires_capability__)
+# define _LIBCPP_REQUIRES_CAPABILITY(...) __attribute__((__requires_capability__(__VA_ARGS__)))
+# else
+# define _LIBCPP_REQUIRES_CAPABILITY(...)
+# endif
+
# if defined(_LIBCPP_ABI_MICROSOFT) && __has_declspec_attribute(empty_bases)
# define _LIBCPP_DECLSPEC_EMPTY_BASES __declspec(empty_bases)
# else
diff --git a/libcxx/include/__mutex/lock_guard.h b/libcxx/include/__mutex/lock_guard.h
index a529c552a1df0..67a25ed2f8a89 100644
--- a/libcxx/include/__mutex/lock_guard.h
+++ b/libcxx/include/__mutex/lock_guard.h
@@ -19,7 +19,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _Mutex>
-class _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) lock_guard {
+class _LIBCPP_SCOPED_LOCKABLE lock_guard {
public:
typedef _Mutex mutex_type;
@@ -27,16 +27,14 @@ class _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) lock_guard {
mutex_type& __m_;
public:
- [[__nodiscard__]]
- _LIBCPP_HIDE_FROM_ABI explicit lock_guard(mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m))
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI explicit lock_guard(mutex_type& __m) _LIBCPP_ACQUIRE_CAPABILITY(__m)
: __m_(__m) {
__m_.lock();
}
- [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI lock_guard(mutex_type& __m, adopt_lock_t)
- _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m))
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI lock_guard(mutex_type& __m, adopt_lock_t) _LIBCPP_REQUIRES_CAPABILITY(__m)
: __m_(__m) {}
- _LIBCPP_HIDE_FROM_ABI ~lock_guard() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) { __m_.unlock(); }
+ _LIBCPP_RELEASE_CAPABILITY _LIBCPP_HIDE_FROM_ABI ~lock_guard() { __m_.unlock(); }
lock_guard(lock_guard const&) = delete;
lock_guard& operator=(lock_guard const&) = delete;
diff --git a/libcxx/include/__mutex/mutex.h b/libcxx/include/__mutex/mutex.h
index e2faeacd9b20a..4355d547ecf4d 100644
--- a/libcxx/include/__mutex/mutex.h
+++ b/libcxx/include/__mutex/mutex.h
@@ -22,7 +22,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
_LIBCPP_BEGIN_EXPLICIT_ABI_ANNOTATIONS
-class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mutex {
+class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_CAPABILITY("mutex") mutex {
__libcpp_mutex_t __m_ = _LIBCPP_MUTEX_INITIALIZER;
public:
@@ -37,9 +37,9 @@ class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mut
~mutex() _NOEXCEPT;
# endif
- void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability());
- bool try_lock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_capability(true));
- void unlock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability());
+ _LIBCPP_ACQUIRE_CAPABILITY() void lock();
+ _LIBCPP_TRY_ACQUIRE_CAPABILITY(true) bool try_lock() _NOEXCEPT;
+ _LIBCPP_RELEASE_CAPABILITY void unlock() _NOEXCEPT;
typedef __libcpp_mutex_t* native_handle_type;
_LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() { return &__m_; }
diff --git a/libcxx/include/mutex b/libcxx/include/mutex
index 2af2a6be5849e..838f31c2b3fee 100644
--- a/libcxx/include/mutex
+++ b/libcxx/include/mutex
@@ -435,7 +435,7 @@ public:
};
template <class _Mutex>
-class _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) scoped_lock<_Mutex> {
+class _LIBCPP_SCOPED_LOCKABLE scoped_lock<_Mutex> {
public:
typedef _Mutex mutex_type;
@@ -443,16 +443,15 @@ private:
mutex_type& __m_;
public:
- [[nodiscard]]
- _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m))
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(mutex_type& __m) _LIBCPP_ACQUIRE_CAPABILITY(__m)
: __m_(__m) {
__m_.lock();
}
- ~scoped_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) { __m_.unlock(); }
+ _LIBCPP_RELEASE_CAPABILITY _LIBCPP_HIDE_FROM_ABI ~scoped_lock() { __m_.unlock(); }
- [[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(adopt_lock_t, mutex_type& __m)
- _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m))
+ [[nodiscard]]
+ _LIBCPP_HIDE_FROM_ABI explicit scoped_lock(adopt_lock_t, mutex_type& __m) _LIBCPP_REQUIRES_CAPABILITY(__m)
: __m_(__m) {}
scoped_lock(scoped_lock const&) = delete;
diff --git a/libcxx/include/shared_mutex b/libcxx/include/shared_mutex
index 795369c7a1cf3..749fd178c35a6 100644
--- a/libcxx/include/shared_mutex
+++ b/libcxx/include/shared_mutex
@@ -185,7 +185,7 @@ struct _LIBCPP_EXPORTED_FROM_ABI __shared_mutex_base {
_LIBCPP_END_EXPLICIT_ABI_ANNOTATIONS
# if _LIBCPP_STD_VER >= 17
-class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_THREAD_SAFETY_ANNOTATION(__capability__("shared_mutex")) shared_mutex {
+class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_CAPABILITY("shared_mutex") shared_mutex {
__shared_mutex_base __base_;
public:
@@ -196,25 +196,16 @@ public:
shared_mutex& operator=(const shared_mutex&) = delete;
// Exclusive ownership
- _LIBCPP_HIDE_FROM_ABI void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(__acquire_capability__()) {
- return __base_.lock();
- }
- _LIBCPP_HIDE_FROM_ABI bool try_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_capability__(true)) {
- return __base_.try_lock();
- }
- _LIBCPP_HIDE_FROM_ABI void unlock() _LIBCPP_THREAD_SAFETY_ANNOTATION(__release_capability__()) {
- return __base_.unlock();
- }
+ _LIBCPP_ACQUIRE_CAPABILITY() _LIBCPP_HIDE_FROM_ABI void lock() { return __base_.lock(); }
+ _LIBCPP_TRY_ACQUIRE_CAPABILITY(true) _LIBCPP_HIDE_FROM_ABI bool try_lock() { return __base_.try_lock(); }
+ _LIBCPP_RELEASE_CAPABILITY _LIBCPP_HIDE_FROM_ABI void unlock() { return __base_.unlock(); }
// Shared ownership
- _LIBCPP_HIDE_FROM_ABI void lock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(__acquire_shared_capability__()) {
- return __base_.lock_shared();
- }
- _LIBCPP_HIDE_FROM_ABI bool try_lock_shared()
- _LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_shared_capability__(true)) {
+ _LIBCPP_ACQUIRE_SHARED_CAPABILITY _LIBCPP_HIDE_FROM_ABI void lock_shared() { return __base_.lock_shared(); }
+ _LIBCPP_TRY_ACQUIRE_SHARED_CAPABILITY(true) _LIBCPP_HIDE_FROM_ABI bool try_lock_shared() {
return __base_.try_lock_shared();
}
- _LIBCPP_HIDE_FROM_ABI void unlock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(__release_shared_capability__()) {
+ _LIBCPP_RELEASE_SHARED_CAPABILITY _LIBCPP_HIDE_FROM_ABI void unlock_shared() {
return __base_.unlock_shared();
}
@@ -224,8 +215,7 @@ public:
# endif
_LIBCPP_BEGIN_EXPLICIT_ABI_ANNOTATIONS
-class _LIBCPP_EXPORTED_FROM_ABI
-_LIBCPP_THREAD_SAFETY_ANNOTATION(__capability__("shared_timed_mutex")) shared_timed_mutex {
+class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_CAPABILITY("shared_timed_mutex") shared_timed_mutex {
__shared_mutex_base __base_;
public:
@@ -236,17 +226,17 @@ public:
shared_timed_mutex& operator=(const shared_timed_mutex&) = delete;
// Exclusive ownership
- void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(__acquire_capability__());
- bool try_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_capability__(true));
+ void lock() _LIBCPP_ACQUIRE_CAPABILITY();
+ _LIBCPP_TRY_ACQUIRE_CAPABILITY(true) bool try_lock();
template <class _Rep, class _Period>
- _LIBCPP_HIDE_FROM_ABI bool try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time)
- _LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_capability__(true)) {
+ _LIBCPP_TRY_ACQUIRE_CAPABILITY(true) _LIBCPP_HIDE_FROM_ABI bool
+ try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time) {
return try_lock_until(chrono::steady_clock::now() + __rel_time);
}
template <class _Clock, class _Duration>
- _LIBCPP_HIDE_FROM_ABI bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time)
- _LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_capability__(true)) {
+ _LIBCPP_TRY_ACQUIRE_CAPABILITY(true) _LIBCPP_HIDE_FROM_ABI bool
+ try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time) {
unique_lock<mutex> __lk(__base_.__mut_);
if (__base_.__state_ & __base_.__write_entered_) {
while (true) {
@@ -273,20 +263,20 @@ public:
return true;
}
- void unlock() _LIBCPP_THREAD_SAFETY_ANNOTATION(__release_capability__());
+ _LIBCPP_RELEASE_CAPABILITY void unlock();
// Shared ownership
- void lock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(__acquire_shared_capability__());
- bool try_lock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_shared_capability__(true));
+ _LIBCPP_ACQUIRE_SHARED_CAPABILITY void lock_shared();
+ _LIBCPP_TRY_ACQUIRE_SHARED_CAPABILITY(true) bool try_lock_shared();
template <class _Rep, class _Period>
- _LIBCPP_HIDE_FROM_ABI bool try_lock_shared_for(const chrono::duration<_Rep, _Period>& __rel_time)
- _LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_shared_capability__(true)) {
+ _LIBCPP_TRY_ACQUIRE_SHARED_CAPABILITY(true) _LIBCPP_HIDE_FROM_ABI bool
+ try_lock_shared_for(const chrono::duration<_Rep, _Period>& __rel_time) {
return try_lock_shared_until(chrono::steady_clock::now() + __rel_time);
}
template <class _Clock, class _Duration>
- _LIBCPP_HIDE_FROM_ABI bool try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& __abs_time)
- _LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_shared_capability__(true)) {
+ _LIBCPP_TRY_ACQUIRE_SHARED_CAPABILITY(true) _LIBCPP_HIDE_FROM_ABI bool
+ try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& __abs_time) {
unique_lock<mutex> __lk(__base_.__mut_);
if ((__base_.__state_ & __base_.__write_entered_) ||
(__base_.__state_ & __base_.__n_readers_) == __base_.__n_readers_) {
@@ -305,7 +295,7 @@ public:
return true;
}
- void unlock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(__release_shared_capability__());
+ _LIBCPP_RELEASE_SHARED_CAPABILITY void unlock_shared();
};
_LIBCPP_END_EXPLICIT_ABI_ANNOTATIONS
More information about the libcxx-commits
mailing list