/
thread_safety_annotations.hpp
278 lines (253 loc) · 11.7 KB
/
thread_safety_annotations.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCPPUTILS__THREAD_SAFETY_ANNOTATIONS_HPP_
#define RCPPUTILS__THREAD_SAFETY_ANNOTATIONS_HPP_
#include <mutex>
/*! \file thread_safety_annotations.hpp
* \brief Enable thread safety attributes only with clang+libcxx.
*
* Technically they would work with clang without libcxx, on manually-annotated thread safety
* primitives, but this use case causes the error of annotating against non-annotated libstdc++
* types. Users that wish to annotate their threading library will need to define these macros
* separately for that case.
*
* The attributes can be safely erased when compiling with other compilers.
*
*
* Macro descriptions were obtained from llvm's thread safety annotation documentation, see
* [their documentation](https://clang.llvm.org/docs/ThreadSafetyAnalysis.html) for more info
*/
// Prefixing all macros to avoid potential conflict with other projects.
/**
* \def RCPPUTILS_THREAD_ANNOTATION_ATTRIBUTE_IMPL(x)
* \brief Enable thread safety attributes only with clang.
*
* The attributes can be safely erased when compiling with other compilers.
* https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#mutex-h
*/
#if defined(__clang__) && defined(_LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS) && (!defined(SWIG))
#define RCPPUTILS_THREAD_ANNOTATION_ATTRIBUTE_IMPL(x) __attribute__((x))
#else
#define RCPPUTILS_THREAD_ANNOTATION_ATTRIBUTE_IMPL(x) // no-op
#endif
/**
* \brief Defined for negation functionality
*
* libcxx does not define this operator, needed for negative capabilities
* TODO Here until someone has a better idea
*/
inline const std::mutex & operator!(const std::mutex & a)
{
return a;
}
/**
* \def RCPPUTILS_TSA_CAPABILITY
* \brief Attribute on classes, which specifies that objects of the class can be used as a
* capability.
*
* The string argument specifies the kind of capability in error
* messages, e.g. "mutex". See the Container example given above, or the Mutex class in mutex.h at:
* https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#capability-string
*/
#define RCPPUTILS_TSA_CAPABILITY(x) \
RCPPUTILS_THREAD_ANNOTATION_ATTRIBUTE_IMPL(capability(x))
/**
* \def RCPPUTILS_TSA_SCOPED_CAPABILITY
* \brief Attribute on classes that implement RAII-style locking, in which a capability is acquired
* in the constructor, and released in the destructor
*
* Such classes require special handling because the constructor and destructor refer to the
* capability via different names; see the MutexLocker class in mutex.h, at:
* https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#scoped-capability
*/
#define RCPPUTILS_TSA_SCOPED_CAPABILITY \
RCPPUTILS_THREAD_ANNOTATION_ATTRIBUTE_IMPL(scoped_lockable)
/**
* \def RCPPUTILS_TSA_GUARDED_BY
* \brief Attribute on data members, which declares that the data member is protected by the given
* capability.
*
* Read operations on the data require shared access, while write operations require exclusive
* access. https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#guarded-by-c-and-pt-guarded-by-c
*/
#define RCPPUTILS_TSA_GUARDED_BY(x) \
RCPPUTILS_THREAD_ANNOTATION_ATTRIBUTE_IMPL(guarded_by(x))
/**
* \def RCPPUTILS_TSA_PT_GUARDED_BY
* \brief Similar to RCPPUTILS_TSA_GUARDED_BY, but is intended for use on pointers and smart
* pointers.
*
* There is no constraint on the data member itself, but the data that it points to is protected by
* the given capability.
* https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#guarded-by-c-and-pt-guarded-by-c
*/
#define RCPPUTILS_TSA_PT_GUARDED_BY(x) \
RCPPUTILS_THREAD_ANNOTATION_ATTRIBUTE_IMPL(pt_guarded_by(x))
/**
* \def RCPPUTILS_TSA_ACQUIRED_BEFORE
* \brief Attribute on member declarations, specifically declarations of mutexes or other
* capabilities.
*
* These declarations enforce a particular order in which the mutexes must be acquired, in order to
* prevent deadlock.
* https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#acquired-before-acquired-after
*/
#define RCPPUTILS_TSA_ACQUIRED_BEFORE(...) \
RCPPUTILS_THREAD_ANNOTATION_ATTRIBUTE_IMPL(acquired_before(__VA_ARGS__))
/**
* \def RCPPUTILS_TSA_ACQUIRED_AFTER
* \brief Attribute on member declarations, specifically declarations of mutexes or other
* capabilities.
*
* These declarations enforce a particular order in which the mutexes must be acquired, in order
* to prevent deadlock.
* https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#acquired-before-acquired-after
*/
#define RCPPUTILS_TSA_ACQUIRED_AFTER(...) \
RCPPUTILS_THREAD_ANNOTATION_ATTRIBUTE_IMPL(acquired_after(__VA_ARGS__))
/**
* \def RCPPUTILS_TSA_REQUIRES
* \brief Attribute on functions or methods, which declares that the calling thread must have
* exclusive access to the given capabilities.
*
* More than one capability may be specified. The capabilities must be held on entry to the
* function, and must still be held on exit.
* https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#requires-requires-shared
*/
#define RCPPUTILS_TSA_REQUIRES(...) \
RCPPUTILS_THREAD_ANNOTATION_ATTRIBUTE_IMPL(requires_capability(__VA_ARGS__))
/**
* \def RCPPUTILS_TSA_REQUIRES_SHARED
* \brief Attribute on functions or methods, which declares that the calling thread must have
* shared access to the given capabilities.
*
* More than one capability may be specified. The capabilities must be held on entry to the
* function, and must still be held on exit.
* https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#requires-requires-shared
*/
#define RCPPUTILS_TSA_REQUIRES_SHARED(...) \
RCPPUTILS_THREAD_ANNOTATION_ATTRIBUTE_IMPL(requires_shared_capability(__VA_ARGS__))
/**
* \def RCPPUTILS_TSA_ACQUIRE
* \brief Attribute on functions or methods, which declares that the function acquires a
* capability, but does not release it.
*
* The caller must not hold the given capability on entry, and it will hold the capability on exit.
* https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#acquire-acquire-shared-release-release-shared
*/
#define RCPPUTILS_TSA_ACQUIRE(...) \
RCPPUTILS_THREAD_ANNOTATION_ATTRIBUTE_IMPL(acquire_capability(__VA_ARGS__))
/**
* \def RCPPUTILS_TSA_ACQUIRE_SHARED
* \brief Attribute on functions or methods, which declares that the function acquires a shared
* capability, but does not release it.
*
* The caller must not hold the given capability on entry, and it will hold the capability on exit.
* https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#acquire-acquire-shared-release-release-shared
*/
#define RCPPUTILS_TSA_ACQUIRE_SHARED(...) \
RCPPUTILS_THREAD_ANNOTATION_ATTRIBUTE_IMPL(acquire_shared_capability(__VA_ARGS__))
/**
* \def RCPPUTILS_TSA_RELEASE
* \brief Declare that the function releases the given capability.
*
* The caller must hold the capability on entry, and will no longer hold it on exit. It does not
* matter whether the given capability is shared or exclusive.
* https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#acquire-acquire-shared-release-release-shared
*/
#define RCPPUTILS_TSA_RELEASE(...) \
RCPPUTILS_THREAD_ANNOTATION_ATTRIBUTE_IMPL(release_capability(__VA_ARGS__))
/**
* \def RCPPUTILS_TSA_RELEASE_SHARED
* \brief Declare that the function releases the given shared capability.
*
* The caller must hold the shared capability on entry, and will no longer hold it on exit. It does
* not matter whether the given capability is shared or exclusive.
* https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#acquire-acquire-shared-release-release-shared
*/
#define RCPPUTILS_TSA_RELEASE_SHARED(...) \
RCPPUTILS_THREAD_ANNOTATION_ATTRIBUTE_IMPL(release_shared_capability(__VA_ARGS__))
/**
* \def RCPPUTILS_TSA_TRY_ACQUIRE
* \brief Attempts to RCPPUTILS_TSA_ACQUIRE, but its return value will indicate whether it
* succeeded or failed.
*
* https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#try-acquire-bool-try-acquire-shared-bool
*/
#define RCPPUTILS_TSA_TRY_ACQUIRE(...) \
RCPPUTILS_THREAD_ANNOTATION_ATTRIBUTE_IMPL(try_acquire_capability(__VA_ARGS__))
/**
* \def RCPPUTILS_TSA_TRY_ACQUIRE_SHARED
* \brief Attempts to RCPPUTILS_TSA_ACQUIRE_SHARED, but its return value will indicate whether it
* succeeded or failed.
*
* https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#try-acquire-bool-try-acquire-shared-bool
*/
#define RCPPUTILS_TSA_TRY_ACQUIRE_SHARED(...) \
RCPPUTILS_THREAD_ANNOTATION_ATTRIBUTE_IMPL(try_acquire_shared_capability(__VA_ARGS__))
/**
* \def RCPPUTILS_TSA_EXCLUDES
* \brief attribute prevents deadlock, by making sure that a mutex is not held.
*
* However, EXCLUDES is an optional attribute, and does not provide the same safety guarantee as
* RCPPUTILS_TSA_REQUIRES. In particular:
* - A function which acquires a capability does not have to exclude it.
* - A function which calls a function that excludes a capability does not have transitively
* - exclude that capability.
* https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#negative-capabilities
*/
#define RCPPUTILS_TSA_EXCLUDES(...) \
RCPPUTILS_THREAD_ANNOTATION_ATTRIBUTE_IMPL(locks_excluded(__VA_ARGS__))
/**
* \def RCPPUTILS_TSA_ASSERT_CAPABILITY
* \brief Perform a run-time test to see whether the calling thread holds the given capability.
*
* The function is assumed to fail (no return) if the capability is not held
* https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#assert-capability-and-assert-shared-capability
*/
#define RCPPUTILS_TSA_ASSERT_CAPABILITY(...) \
RCPPUTILS_THREAD_ANNOTATION_ATTRIBUTE_IMPL(assert_capability(__VA_ARGS__))
/**
* \def RCPPUTILS_TSA_ASSERT_SHARED_CAPABILITY
* \brief Perform a run-time test to see whether the calling thread holds the given shared
* capability.
*
* The function is assumed to fail (no return) if the capability is not held.
* https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#assert-capability-and-assert-shared-capability
*/
#define RCPPUTILS_TSA_ASSERT_SHARED_CAPABILITY(...) \
RCPPUTILS_THREAD_ANNOTATION_ATTRIBUTE_IMPL(assert_shared_capability(__VA_ARGS__))
/**
* \def RCPPUTILS_TSA_RETURN_CAPABILITY
* \brief Attribute on functions or methods, which declares that the function returns a reference
* to the given capability.
*
* It is used to annotate getter methods that return mutexes.
* https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#return-capability-c
*/
#define RCPPUTILS_TSA_RETURN_CAPABILITY(x) \
RCPPUTILS_THREAD_ANNOTATION_ATTRIBUTE_IMPL(lock_returned(x))
/**
* \def RCPPUTILS_TSA_NO_THREAD_SAFETY_ANALYSIS
* \brief Attribute on functions or methods, which turns off thread safety checking for that
* method.
*
* RCPPUTILS_TSA_NO_THREAD_SAFETY_ANALYSIS provides an escape hatch for functions which are
* either (1) deliberately thread-unsafe, or (2) are thread-safe, but too complicated for the
* analysis to understand. Reasons for (2) will be described in the Known Limitations, below.
* https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#return-capability-c
*/
#define RCPPUTILS_TSA_NO_THREAD_SAFETY_ANALYSIS \
RCPPUTILS_THREAD_ANNOTATION_ATTRIBUTE_IMPL(no_thread_safety_analysis)
#endif // RCPPUTILS__THREAD_SAFETY_ANNOTATIONS_HPP_