be/src/common/thread_safety_annotations.h
Line | Count | Source |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | |
18 | | // Thread safety annotation macros and annotated mutex wrappers for |
19 | | // Clang's -Wthread-safety static analysis. |
20 | | // Reference: https://clang.llvm.org/docs/ThreadSafetyAnalysis.html |
21 | | |
22 | | #pragma once |
23 | | |
24 | | #include <mutex> |
25 | | |
26 | | // Enable thread safety attributes only with clang. |
27 | | // The attributes can be safely erased when compiling with other compilers. |
28 | | #if defined(__clang__) && (!defined(SWIG)) |
29 | | #define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) |
30 | | #else |
31 | | #define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op |
32 | | #endif |
33 | | |
34 | | #define TSA_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(capability(x)) |
35 | | |
36 | | #define TSA_SCOPED_CAPABILITY THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable) |
37 | | |
38 | | #define TSA_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) |
39 | | |
40 | | #define TSA_PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x)) |
41 | | |
42 | | #define TSA_ACQUIRED_BEFORE(...) THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__)) |
43 | | |
44 | | #define TSA_ACQUIRED_AFTER(...) THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__)) |
45 | | |
46 | | #define TSA_REQUIRES(...) THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__)) |
47 | | |
48 | | #define TSA_REQUIRES_SHARED(...) \ |
49 | | THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__)) |
50 | | |
51 | | #define TSA_ACQUIRE(...) THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__)) |
52 | | |
53 | | #define TSA_ACQUIRE_SHARED(...) \ |
54 | | THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__)) |
55 | | |
56 | | #define TSA_RELEASE(...) THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__)) |
57 | | |
58 | | #define TSA_RELEASE_SHARED(...) \ |
59 | | THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__)) |
60 | | |
61 | | #define TSA_TRY_ACQUIRE(...) THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__)) |
62 | | |
63 | | #define TSA_TRY_ACQUIRE_SHARED(...) \ |
64 | | THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__)) |
65 | | |
66 | | #define TSA_EXCLUDES(...) THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__)) |
67 | | |
68 | | #define TSA_ASSERT_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x)) |
69 | | |
70 | | #define TSA_ASSERT_SHARED_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x)) |
71 | | |
72 | | #define TSA_RETURN_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) |
73 | | |
74 | | #define TSA_NO_THREAD_SAFETY_ANALYSIS THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) |
75 | | |
76 | | // Annotated mutex wrapper for use with Clang thread safety analysis. |
77 | | // Wraps std::mutex and provides the CAPABILITY annotation so that |
78 | | // GUARDED_BY / REQUIRES / etc. annotations can reference it. |
79 | | class TSA_CAPABILITY("mutex") AnnotatedMutex { |
80 | | public: |
81 | 7.19M | void lock() TSA_ACQUIRE() { _mutex.lock(); } |
82 | 7.19M | void unlock() TSA_RELEASE() { _mutex.unlock(); } |
83 | 0 | bool try_lock() TSA_TRY_ACQUIRE(true) { return _mutex.try_lock(); } |
84 | | |
85 | | // Access the underlying std::mutex (e.g., for std::condition_variable). |
86 | | // Use with care — this bypasses thread safety annotations. |
87 | 0 | std::mutex& native_handle() { return _mutex; } |
88 | | |
89 | | private: |
90 | | std::mutex _mutex; |
91 | | }; |
92 | | |
93 | | // RAII scoped lock guard annotated for thread safety analysis. |
94 | | template <typename MutexType> |
95 | | class TSA_SCOPED_CAPABILITY AnnotatedLockGuard { |
96 | | public: |
97 | 7.19M | explicit AnnotatedLockGuard(MutexType& mu) TSA_ACQUIRE(mu) : _mu(mu) { _mu.lock(); } |
98 | 7.19M | ~AnnotatedLockGuard() TSA_RELEASE() { _mu.unlock(); } |
99 | | |
100 | | AnnotatedLockGuard(const AnnotatedLockGuard&) = delete; |
101 | | AnnotatedLockGuard& operator=(const AnnotatedLockGuard&) = delete; |
102 | | |
103 | | private: |
104 | | MutexType& _mu; |
105 | | }; |