Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion libcxx/.clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -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',
]
Expand Down
5 changes: 0 additions & 5 deletions libcxx/docs/UserDocumentation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,6 @@ enable or disable extended libc++ behavior.
ensure that the appropriate experimental library (usually ``libc++experimental.a``)
is linked into their program.

**_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS**:
This macro is used to enable -Wthread-safety annotations on libc++'s
``std::mutex`` and ``std::lock_guard``. By default, these annotations are
disabled and must be manually enabled by the user.

**_LIBCPP_HARDENING_MODE**:
This macro is used to choose the :ref:`hardening mode <using-hardening-modes>`.

Expand Down
71 changes: 54 additions & 17 deletions libcxx/include/__config
Original file line number Diff line number Diff line change
Expand Up @@ -910,23 +910,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__)
Expand Down Expand Up @@ -1154,6 +1137,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
Expand Down
10 changes: 4 additions & 6 deletions libcxx/include/__mutex/lock_guard.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,22 @@
_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;

private:
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;
Expand Down
8 changes: 4 additions & 4 deletions libcxx/include/__mutex/mutex.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

_LIBCPP_BEGIN_NAMESPACE_STD

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:
Expand All @@ -36,9 +36,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_; }
Expand Down
11 changes: 5 additions & 6 deletions libcxx/include/mutex
Original file line number Diff line number Diff line change
Expand Up @@ -434,24 +434,23 @@ 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;

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;
Expand Down
56 changes: 22 additions & 34 deletions libcxx/include/shared_mutex
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ struct _LIBCPP_EXPORTED_FROM_ABI __shared_mutex_base {
};

# 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:
Expand All @@ -194,35 +194,23 @@ 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__()) {
return __base_.unlock_shared();
}
_LIBCPP_RELEASE_SHARED_CAPABILITY _LIBCPP_HIDE_FROM_ABI void unlock_shared() { return __base_.unlock_shared(); }

// typedef __shared_mutex_base::native_handle_type native_handle_type;
// _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() { return __base::unlock_shared(); }
};
# endif

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:
Expand All @@ -233,17 +221,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) {
Expand All @@ -270,20 +258,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_) {
Expand All @@ -302,7 +290,7 @@ public:
return true;
}

void unlock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(__release_shared_capability__());
_LIBCPP_RELEASE_SHARED_CAPABILITY void unlock_shared();
};

template <class _Mutex>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@

// <mutex>

// This test does not define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS so it
// should compile without any warnings or errors even though this pattern is not
// understood by the thread safety annotations.
// This test does not set -Wthread-safety so it should compile without any warnings or errors even though this pattern
// is not understood by the thread safety annotations.

#include <mutex>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@
//
//===----------------------------------------------------------------------===//

// On Windows Clang bugs out when both __declspec and __attribute__ are present,
// the processing goes awry preventing the definition of the types.
// XFAIL: msvc

// UNSUPPORTED: no-threads
// REQUIRES: thread-safety

// <mutex>

// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS
// GCC doesn't have thread safety attributes
// UNSUPPORTED: gcc

// ADDITIONAL_COMPILE_FLAGS: -Wthread-safety

// XFAIL: FROZEN-CXX03-HEADERS-FIXME

#include <mutex>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@
//
//===----------------------------------------------------------------------===//

// On Windows Clang bugs out when both __declspec and __attribute__ are present,
// the processing goes awry preventing the definition of the types.
// XFAIL: msvc

// UNSUPPORTED: no-threads
// REQUIRES: thread-safety

// <mutex>

// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS
// GCC doesn't have thread safety attributes
// UNSUPPORTED: gcc

// ADDITIONAL_COMPILE_FLAGS: -Wthread-safety

// XFAIL: FROZEN-CXX03-HEADERS-FIXME

#include <mutex>

Expand Down
Loading
Loading