jamesr updated this revision to Diff 41581.
jamesr added a comment.
Updates the macros to avoid defining anything if _LIBCPP_THREAD_ANNOTATION is
already defined and to define _LIBCPP_THREAD_ANNOTATION to nothing if __clang__
is not set, __has_attribute(acquire_capability) is not set, or
_LIBCPP_HAS_NO_THREAD_ANNOTATIONS is set.
It turns out there's not a clean feature guard for the thread safety
annotations (i.e. no __has_feature() guard). The annotations were added over
time to clang. I'm not sure at which point the feature was considered stable
enough for general use. Looking at clang's history the most recently added
annotation out of the ones this patch uses is acquire_capability which was
added in this commit: https://llvm.org/svn/llvm-project/cfe/trunk@201890, so
I'm testing for that annotation to test for support for the feature as a whole.
It's quite possible that there are revisions of clang after the annotation
support was added that contain bugs that make the annotations not very useful
but the fix for any users trying to use such versions of clang is easy - just
avoid passing -Wthread-safety to these versions of clang.
http://reviews.llvm.org/D14731
Files:
include/__config
include/__mutex_base
Index: include/__mutex_base
===================================================================
--- include/__mutex_base
+++ include/__mutex_base
@@ -26,7 +26,15 @@
#ifndef _LIBCPP_HAS_NO_THREADS
-class _LIBCPP_TYPE_VIS mutex
+#ifndef _LIBCPP_THREAD_ANNOTATION
+# ifndef _LIBCPP_HAS_NO_THREAD_ANNOTATIONS
+# define _LIBCPP_THREAD_ANNOTATION(x) __attribute__((x))
+# else
+# define _LIBCPP_THREAD_ANNOTATION(x)
+# endif
+#endif // _LIBCPP_THREAD_ANNOTATION
+
+class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_ANNOTATION(capability("mutex")) mutex
{
pthread_mutex_t __m_;
@@ -44,9 +52,9 @@
mutex& operator=(const mutex&);// = delete;
public:
- void lock();
- bool try_lock() _NOEXCEPT;
- void unlock() _NOEXCEPT;
+ void lock() _LIBCPP_THREAD_ANNOTATION(acquire_capability());
+ bool try_lock() _NOEXCEPT
_LIBCPP_THREAD_ANNOTATION(try_acquire_capability(true));
+ void unlock() _NOEXCEPT _LIBCPP_THREAD_ANNOTATION(release_capability());
typedef pthread_mutex_t* native_handle_type;
_LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return
&__m_;}
@@ -71,7 +79,7 @@
#endif
template <class _Mutex>
-class _LIBCPP_TYPE_VIS_ONLY lock_guard
+class _LIBCPP_TYPE_VIS_ONLY _LIBCPP_THREAD_ANNOTATION(scoped_lockable)
lock_guard
{
public:
typedef _Mutex mutex_type;
@@ -81,13 +89,13 @@
public:
_LIBCPP_INLINE_VISIBILITY
- explicit lock_guard(mutex_type& __m)
+ explicit lock_guard(mutex_type& __m)
_LIBCPP_THREAD_ANNOTATION(acquire_capability(__m))
: __m_(__m) {__m_.lock();}
_LIBCPP_INLINE_VISIBILITY
- lock_guard(mutex_type& __m, adopt_lock_t)
+ lock_guard(mutex_type& __m, adopt_lock_t)
_LIBCPP_THREAD_ANNOTATION(requires_capability(__m))
: __m_(__m) {}
_LIBCPP_INLINE_VISIBILITY
- ~lock_guard() {__m_.unlock();}
+ ~lock_guard() _LIBCPP_THREAD_ANNOTATION(release_capability())
{__m_.unlock();}
private:
lock_guard(lock_guard const&);// = delete;
Index: include/__config
===================================================================
--- include/__config
+++ include/__config
@@ -825,6 +825,11 @@
#define _LIBCPP_HAS_NO_ATOMIC_HEADER
#endif
+#if (!defined(_LIBCPP_HAS_NO_THREAD_ANNOTATIONS) && (!defined(__clang__) \
+ || !__has_attribute(acquire_capability)))
+#define _LIBCPP_HAS_NO_THREAD_ANNOTATIONS
+#endif
+
#endif // __cplusplus
#endif // _LIBCPP_CONFIG
Index: include/__mutex_base
===================================================================
--- include/__mutex_base
+++ include/__mutex_base
@@ -26,7 +26,15 @@
#ifndef _LIBCPP_HAS_NO_THREADS
-class _LIBCPP_TYPE_VIS mutex
+#ifndef _LIBCPP_THREAD_ANNOTATION
+# ifndef _LIBCPP_HAS_NO_THREAD_ANNOTATIONS
+# define _LIBCPP_THREAD_ANNOTATION(x) __attribute__((x))
+# else
+# define _LIBCPP_THREAD_ANNOTATION(x)
+# endif
+#endif // _LIBCPP_THREAD_ANNOTATION
+
+class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_ANNOTATION(capability("mutex")) mutex
{
pthread_mutex_t __m_;
@@ -44,9 +52,9 @@
mutex& operator=(const mutex&);// = delete;
public:
- void lock();
- bool try_lock() _NOEXCEPT;
- void unlock() _NOEXCEPT;
+ void lock() _LIBCPP_THREAD_ANNOTATION(acquire_capability());
+ bool try_lock() _NOEXCEPT _LIBCPP_THREAD_ANNOTATION(try_acquire_capability(true));
+ void unlock() _NOEXCEPT _LIBCPP_THREAD_ANNOTATION(release_capability());
typedef pthread_mutex_t* native_handle_type;
_LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;}
@@ -71,7 +79,7 @@
#endif
template <class _Mutex>
-class _LIBCPP_TYPE_VIS_ONLY lock_guard
+class _LIBCPP_TYPE_VIS_ONLY _LIBCPP_THREAD_ANNOTATION(scoped_lockable) lock_guard
{
public:
typedef _Mutex mutex_type;
@@ -81,13 +89,13 @@
public:
_LIBCPP_INLINE_VISIBILITY
- explicit lock_guard(mutex_type& __m)
+ explicit lock_guard(mutex_type& __m) _LIBCPP_THREAD_ANNOTATION(acquire_capability(__m))
: __m_(__m) {__m_.lock();}
_LIBCPP_INLINE_VISIBILITY
- lock_guard(mutex_type& __m, adopt_lock_t)
+ lock_guard(mutex_type& __m, adopt_lock_t) _LIBCPP_THREAD_ANNOTATION(requires_capability(__m))
: __m_(__m) {}
_LIBCPP_INLINE_VISIBILITY
- ~lock_guard() {__m_.unlock();}
+ ~lock_guard() _LIBCPP_THREAD_ANNOTATION(release_capability()) {__m_.unlock();}
private:
lock_guard(lock_guard const&);// = delete;
Index: include/__config
===================================================================
--- include/__config
+++ include/__config
@@ -825,6 +825,11 @@
#define _LIBCPP_HAS_NO_ATOMIC_HEADER
#endif
+#if (!defined(_LIBCPP_HAS_NO_THREAD_ANNOTATIONS) && (!defined(__clang__) \
+ || !__has_attribute(acquire_capability)))
+#define _LIBCPP_HAS_NO_THREAD_ANNOTATIONS
+#endif
+
#endif // __cplusplus
#endif // _LIBCPP_CONFIG
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits