ThreadSafetyAnalysis.rst revision 1.1 1 1.1 joerg
2 1.1 joerg ======================
3 1.1 joerg Thread Safety Analysis
4 1.1 joerg ======================
5 1.1 joerg
6 1.1 joerg Introduction
7 1.1 joerg ============
8 1.1 joerg
9 1.1 joerg Clang Thread Safety Analysis is a C++ language extension which warns about
10 1.1 joerg potential race conditions in code. The analysis is completely static (i.e.
11 1.1 joerg compile-time); there is no run-time overhead. The analysis is still
12 1.1 joerg under active development, but it is mature enough to be deployed in an
13 1.1 joerg industrial setting. It is being developed by Google, in collaboration with
14 1.1 joerg CERT/SEI, and is used extensively in Google's internal code base.
15 1.1 joerg
16 1.1 joerg Thread safety analysis works very much like a type system for multi-threaded
17 1.1 joerg programs. In addition to declaring the *type* of data (e.g. ``int``, ``float``,
18 1.1 joerg etc.), the programmer can (optionally) declare how access to that data is
19 1.1 joerg controlled in a multi-threaded environment. For example, if ``foo`` is
20 1.1 joerg *guarded by* the mutex ``mu``, then the analysis will issue a warning whenever
21 1.1 joerg a piece of code reads or writes to ``foo`` without first locking ``mu``.
22 1.1 joerg Similarly, if there are particular routines that should only be called by
23 1.1 joerg the GUI thread, then the analysis will warn if other threads call those
24 1.1 joerg routines.
25 1.1 joerg
26 1.1 joerg Getting Started
27 1.1 joerg ----------------
28 1.1 joerg
29 1.1 joerg .. code-block:: c++
30 1.1 joerg
31 1.1 joerg #include "mutex.h"
32 1.1 joerg
33 1.1 joerg class BankAccount {
34 1.1 joerg private:
35 1.1 joerg Mutex mu;
36 1.1 joerg int balance GUARDED_BY(mu);
37 1.1 joerg
38 1.1 joerg void depositImpl(int amount) {
39 1.1 joerg balance += amount; // WARNING! Cannot write balance without locking mu.
40 1.1 joerg }
41 1.1 joerg
42 1.1 joerg void withdrawImpl(int amount) REQUIRES(mu) {
43 1.1 joerg balance -= amount; // OK. Caller must have locked mu.
44 1.1 joerg }
45 1.1 joerg
46 1.1 joerg public:
47 1.1 joerg void withdraw(int amount) {
48 1.1 joerg mu.Lock();
49 1.1 joerg withdrawImpl(amount); // OK. We've locked mu.
50 1.1 joerg } // WARNING! Failed to unlock mu.
51 1.1 joerg
52 1.1 joerg void transferFrom(BankAccount& b, int amount) {
53 1.1 joerg mu.Lock();
54 1.1 joerg b.withdrawImpl(amount); // WARNING! Calling withdrawImpl() requires locking b.mu.
55 1.1 joerg depositImpl(amount); // OK. depositImpl() has no requirements.
56 1.1 joerg mu.Unlock();
57 1.1 joerg }
58 1.1 joerg };
59 1.1 joerg
60 1.1 joerg This example demonstrates the basic concepts behind the analysis. The
61 1.1 joerg ``GUARDED_BY`` attribute declares that a thread must lock ``mu`` before it can
62 1.1 joerg read or write to ``balance``, thus ensuring that the increment and decrement
63 1.1 joerg operations are atomic. Similarly, ``REQUIRES`` declares that
64 1.1 joerg the calling thread must lock ``mu`` before calling ``withdrawImpl``.
65 1.1 joerg Because the caller is assumed to have locked ``mu``, it is safe to modify
66 1.1 joerg ``balance`` within the body of the method.
67 1.1 joerg
68 1.1 joerg The ``depositImpl()`` method does not have ``REQUIRES``, so the
69 1.1 joerg analysis issues a warning. Thread safety analysis is not inter-procedural, so
70 1.1 joerg caller requirements must be explicitly declared.
71 1.1 joerg There is also a warning in ``transferFrom()``, because although the method
72 1.1 joerg locks ``this->mu``, it does not lock ``b.mu``. The analysis understands
73 1.1 joerg that these are two separate mutexes, in two different objects.
74 1.1 joerg
75 1.1 joerg Finally, there is a warning in the ``withdraw()`` method, because it fails to
76 1.1 joerg unlock ``mu``. Every lock must have a corresponding unlock, and the analysis
77 1.1 joerg will detect both double locks, and double unlocks. A function is allowed to
78 1.1 joerg acquire a lock without releasing it, (or vice versa), but it must be annotated
79 1.1 joerg as such (using ``ACQUIRE``/``RELEASE``).
80 1.1 joerg
81 1.1 joerg
82 1.1 joerg Running The Analysis
83 1.1 joerg --------------------
84 1.1 joerg
85 1.1 joerg To run the analysis, simply compile with the ``-Wthread-safety`` flag, e.g.
86 1.1 joerg
87 1.1 joerg .. code-block:: bash
88 1.1 joerg
89 1.1 joerg clang -c -Wthread-safety example.cpp
90 1.1 joerg
91 1.1 joerg Note that this example assumes the presence of a suitably annotated
92 1.1 joerg :ref:`mutexheader` that declares which methods perform locking,
93 1.1 joerg unlocking, and so on.
94 1.1 joerg
95 1.1 joerg
96 1.1 joerg Basic Concepts: Capabilities
97 1.1 joerg ============================
98 1.1 joerg
99 1.1 joerg Thread safety analysis provides a way of protecting *resources* with
100 1.1 joerg *capabilities*. A resource is either a data member, or a function/method
101 1.1 joerg that provides access to some underlying resource. The analysis ensures that
102 1.1 joerg the calling thread cannot access the *resource* (i.e. call the function, or
103 1.1 joerg read/write the data) unless it has the *capability* to do so.
104 1.1 joerg
105 1.1 joerg Capabilities are associated with named C++ objects which declare specific
106 1.1 joerg methods to acquire and release the capability. The name of the object serves
107 1.1 joerg to identify the capability. The most common example is a mutex. For example,
108 1.1 joerg if ``mu`` is a mutex, then calling ``mu.Lock()`` causes the calling thread
109 1.1 joerg to acquire the capability to access data that is protected by ``mu``. Similarly,
110 1.1 joerg calling ``mu.Unlock()`` releases that capability.
111 1.1 joerg
112 1.1 joerg A thread may hold a capability either *exclusively* or *shared*. An exclusive
113 1.1 joerg capability can be held by only one thread at a time, while a shared capability
114 1.1 joerg can be held by many threads at the same time. This mechanism enforces a
115 1.1 joerg multiple-reader, single-writer pattern. Write operations to protected data
116 1.1 joerg require exclusive access, while read operations require only shared access.
117 1.1 joerg
118 1.1 joerg At any given moment during program execution, a thread holds a specific set of
119 1.1 joerg capabilities (e.g. the set of mutexes that it has locked.) These act like keys
120 1.1 joerg or tokens that allow the thread to access a given resource. Just like physical
121 1.1 joerg security keys, a thread cannot make copy of a capability, nor can it destroy
122 1.1 joerg one. A thread can only release a capability to another thread, or acquire one
123 1.1 joerg from another thread. The annotations are deliberately agnostic about the
124 1.1 joerg exact mechanism used to acquire and release capabilities; it assumes that the
125 1.1 joerg underlying implementation (e.g. the Mutex implementation) does the handoff in
126 1.1 joerg an appropriate manner.
127 1.1 joerg
128 1.1 joerg The set of capabilities that are actually held by a given thread at a given
129 1.1 joerg point in program execution is a run-time concept. The static analysis works
130 1.1 joerg by calculating an approximation of that set, called the *capability
131 1.1 joerg environment*. The capability environment is calculated for every program point,
132 1.1 joerg and describes the set of capabilities that are statically known to be held, or
133 1.1 joerg not held, at that particular point. This environment is a conservative
134 1.1 joerg approximation of the full set of capabilities that will actually held by a
135 1.1 joerg thread at run-time.
136 1.1 joerg
137 1.1 joerg
138 1.1 joerg Reference Guide
139 1.1 joerg ===============
140 1.1 joerg
141 1.1 joerg The thread safety analysis uses attributes to declare threading constraints.
142 1.1 joerg Attributes must be attached to named declarations, such as classes, methods,
143 1.1 joerg and data members. Users are *strongly advised* to define macros for the various
144 1.1 joerg attributes; example definitions can be found in :ref:`mutexheader`, below.
145 1.1 joerg The following documentation assumes the use of macros.
146 1.1 joerg
147 1.1 joerg For historical reasons, prior versions of thread safety used macro names that
148 1.1 joerg were very lock-centric. These macros have since been renamed to fit a more
149 1.1 joerg general capability model. The prior names are still in use, and will be
150 1.1 joerg mentioned under the tag *previously* where appropriate.
151 1.1 joerg
152 1.1 joerg
153 1.1 joerg GUARDED_BY(c) and PT_GUARDED_BY(c)
154 1.1 joerg ----------------------------------
155 1.1 joerg
156 1.1 joerg ``GUARDED_BY`` is an attribute on data members, which declares that the data
157 1.1 joerg member is protected by the given capability. Read operations on the data
158 1.1 joerg require shared access, while write operations require exclusive access.
159 1.1 joerg
160 1.1 joerg ``PT_GUARDED_BY`` is similar, but is intended for use on pointers and smart
161 1.1 joerg pointers. There is no constraint on the data member itself, but the *data that
162 1.1 joerg it points to* is protected by the given capability.
163 1.1 joerg
164 1.1 joerg .. code-block:: c++
165 1.1 joerg
166 1.1 joerg Mutex mu;
167 1.1 joerg int *p1 GUARDED_BY(mu);
168 1.1 joerg int *p2 PT_GUARDED_BY(mu);
169 1.1 joerg unique_ptr<int> p3 PT_GUARDED_BY(mu);
170 1.1 joerg
171 1.1 joerg void test() {
172 1.1 joerg p1 = 0; // Warning!
173 1.1 joerg
174 1.1 joerg *p2 = 42; // Warning!
175 1.1 joerg p2 = new int; // OK.
176 1.1 joerg
177 1.1 joerg *p3 = 42; // Warning!
178 1.1 joerg p3.reset(new int); // OK.
179 1.1 joerg }
180 1.1 joerg
181 1.1 joerg
182 1.1 joerg REQUIRES(...), REQUIRES_SHARED(...)
183 1.1 joerg -----------------------------------
184 1.1 joerg
185 1.1 joerg *Previously*: ``EXCLUSIVE_LOCKS_REQUIRED``, ``SHARED_LOCKS_REQUIRED``
186 1.1 joerg
187 1.1 joerg ``REQUIRES`` is an attribute on functions or methods, which
188 1.1 joerg declares that the calling thread must have exclusive access to the given
189 1.1 joerg capabilities. More than one capability may be specified. The capabilities
190 1.1 joerg must be held on entry to the function, *and must still be held on exit*.
191 1.1 joerg
192 1.1 joerg ``REQUIRES_SHARED`` is similar, but requires only shared access.
193 1.1 joerg
194 1.1 joerg .. code-block:: c++
195 1.1 joerg
196 1.1 joerg Mutex mu1, mu2;
197 1.1 joerg int a GUARDED_BY(mu1);
198 1.1 joerg int b GUARDED_BY(mu2);
199 1.1 joerg
200 1.1 joerg void foo() REQUIRES(mu1, mu2) {
201 1.1 joerg a = 0;
202 1.1 joerg b = 0;
203 1.1 joerg }
204 1.1 joerg
205 1.1 joerg void test() {
206 1.1 joerg mu1.Lock();
207 1.1 joerg foo(); // Warning! Requires mu2.
208 1.1 joerg mu1.Unlock();
209 1.1 joerg }
210 1.1 joerg
211 1.1 joerg
212 1.1 joerg ACQUIRE(...), ACQUIRE_SHARED(...), RELEASE(...), RELEASE_SHARED(...)
213 1.1 joerg --------------------------------------------------------------------
214 1.1 joerg
215 1.1 joerg *Previously*: ``EXCLUSIVE_LOCK_FUNCTION``, ``SHARED_LOCK_FUNCTION``,
216 1.1 joerg ``UNLOCK_FUNCTION``
217 1.1 joerg
218 1.1 joerg ``ACQUIRE`` is an attribute on functions or methods, which
219 1.1 joerg declares that the function acquires a capability, but does not release it. The
220 1.1 joerg caller must not hold the given capability on entry, and it will hold the
221 1.1 joerg capability on exit. ``ACQUIRE_SHARED`` is similar.
222 1.1 joerg
223 1.1 joerg ``RELEASE`` and ``RELEASE_SHARED`` declare that the function releases the given
224 1.1 joerg capability. The caller must hold the capability on entry, and will no longer
225 1.1 joerg hold it on exit. It does not matter whether the given capability is shared or
226 1.1 joerg exclusive.
227 1.1 joerg
228 1.1 joerg .. code-block:: c++
229 1.1 joerg
230 1.1 joerg Mutex mu;
231 1.1 joerg MyClass myObject GUARDED_BY(mu);
232 1.1 joerg
233 1.1 joerg void lockAndInit() ACQUIRE(mu) {
234 1.1 joerg mu.Lock();
235 1.1 joerg myObject.init();
236 1.1 joerg }
237 1.1 joerg
238 1.1 joerg void cleanupAndUnlock() RELEASE(mu) {
239 1.1 joerg myObject.cleanup();
240 1.1 joerg } // Warning! Need to unlock mu.
241 1.1 joerg
242 1.1 joerg void test() {
243 1.1 joerg lockAndInit();
244 1.1 joerg myObject.doSomething();
245 1.1 joerg cleanupAndUnlock();
246 1.1 joerg myObject.doSomething(); // Warning, mu is not locked.
247 1.1 joerg }
248 1.1 joerg
249 1.1 joerg If no argument is passed to ``ACQUIRE`` or ``RELEASE``, then the argument is
250 1.1 joerg assumed to be ``this``, and the analysis will not check the body of the
251 1.1 joerg function. This pattern is intended for use by classes which hide locking
252 1.1 joerg details behind an abstract interface. For example:
253 1.1 joerg
254 1.1 joerg .. code-block:: c++
255 1.1 joerg
256 1.1 joerg template <class T>
257 1.1 joerg class CAPABILITY("mutex") Container {
258 1.1 joerg private:
259 1.1 joerg Mutex mu;
260 1.1 joerg T* data;
261 1.1 joerg
262 1.1 joerg public:
263 1.1 joerg // Hide mu from public interface.
264 1.1 joerg void Lock() ACQUIRE() { mu.Lock(); }
265 1.1 joerg void Unlock() RELEASE() { mu.Unlock(); }
266 1.1 joerg
267 1.1 joerg T& getElem(int i) { return data[i]; }
268 1.1 joerg };
269 1.1 joerg
270 1.1 joerg void test() {
271 1.1 joerg Container<int> c;
272 1.1 joerg c.Lock();
273 1.1 joerg int i = c.getElem(0);
274 1.1 joerg c.Unlock();
275 1.1 joerg }
276 1.1 joerg
277 1.1 joerg
278 1.1 joerg EXCLUDES(...)
279 1.1 joerg -------------
280 1.1 joerg
281 1.1 joerg *Previously*: ``LOCKS_EXCLUDED``
282 1.1 joerg
283 1.1 joerg ``EXCLUDES`` is an attribute on functions or methods, which declares that
284 1.1 joerg the caller must *not* hold the given capabilities. This annotation is
285 1.1 joerg used to prevent deadlock. Many mutex implementations are not re-entrant, so
286 1.1 joerg deadlock can occur if the function acquires the mutex a second time.
287 1.1 joerg
288 1.1 joerg .. code-block:: c++
289 1.1 joerg
290 1.1 joerg Mutex mu;
291 1.1 joerg int a GUARDED_BY(mu);
292 1.1 joerg
293 1.1 joerg void clear() EXCLUDES(mu) {
294 1.1 joerg mu.Lock();
295 1.1 joerg a = 0;
296 1.1 joerg mu.Unlock();
297 1.1 joerg }
298 1.1 joerg
299 1.1 joerg void reset() {
300 1.1 joerg mu.Lock();
301 1.1 joerg clear(); // Warning! Caller cannot hold 'mu'.
302 1.1 joerg mu.Unlock();
303 1.1 joerg }
304 1.1 joerg
305 1.1 joerg Unlike ``REQUIRES``, ``EXCLUDES`` is optional. The analysis will not issue a
306 1.1 joerg warning if the attribute is missing, which can lead to false negatives in some
307 1.1 joerg cases. This issue is discussed further in :ref:`negative`.
308 1.1 joerg
309 1.1 joerg
310 1.1 joerg NO_THREAD_SAFETY_ANALYSIS
311 1.1 joerg -------------------------
312 1.1 joerg
313 1.1 joerg ``NO_THREAD_SAFETY_ANALYSIS`` is an attribute on functions or methods, which
314 1.1 joerg turns off thread safety checking for that method. It provides an escape hatch
315 1.1 joerg for functions which are either (1) deliberately thread-unsafe, or (2) are
316 1.1 joerg thread-safe, but too complicated for the analysis to understand. Reasons for
317 1.1 joerg (2) will be described in the :ref:`limitations`, below.
318 1.1 joerg
319 1.1 joerg .. code-block:: c++
320 1.1 joerg
321 1.1 joerg class Counter {
322 1.1 joerg Mutex mu;
323 1.1 joerg int a GUARDED_BY(mu);
324 1.1 joerg
325 1.1 joerg void unsafeIncrement() NO_THREAD_SAFETY_ANALYSIS { a++; }
326 1.1 joerg };
327 1.1 joerg
328 1.1 joerg Unlike the other attributes, NO_THREAD_SAFETY_ANALYSIS is not part of the
329 1.1 joerg interface of a function, and should thus be placed on the function definition
330 1.1 joerg (in the ``.cc`` or ``.cpp`` file) rather than on the function declaration
331 1.1 joerg (in the header).
332 1.1 joerg
333 1.1 joerg
334 1.1 joerg RETURN_CAPABILITY(c)
335 1.1 joerg --------------------
336 1.1 joerg
337 1.1 joerg *Previously*: ``LOCK_RETURNED``
338 1.1 joerg
339 1.1 joerg ``RETURN_CAPABILITY`` is an attribute on functions or methods, which declares
340 1.1 joerg that the function returns a reference to the given capability. It is used to
341 1.1 joerg annotate getter methods that return mutexes.
342 1.1 joerg
343 1.1 joerg .. code-block:: c++
344 1.1 joerg
345 1.1 joerg class MyClass {
346 1.1 joerg private:
347 1.1 joerg Mutex mu;
348 1.1 joerg int a GUARDED_BY(mu);
349 1.1 joerg
350 1.1 joerg public:
351 1.1 joerg Mutex* getMu() RETURN_CAPABILITY(mu) { return μ }
352 1.1 joerg
353 1.1 joerg // analysis knows that getMu() == mu
354 1.1 joerg void clear() REQUIRES(getMu()) { a = 0; }
355 1.1 joerg };
356 1.1 joerg
357 1.1 joerg
358 1.1 joerg ACQUIRED_BEFORE(...), ACQUIRED_AFTER(...)
359 1.1 joerg -----------------------------------------
360 1.1 joerg
361 1.1 joerg ``ACQUIRED_BEFORE`` and ``ACQUIRED_AFTER`` are attributes on member
362 1.1 joerg declarations, specifically declarations of mutexes or other capabilities.
363 1.1 joerg These declarations enforce a particular order in which the mutexes must be
364 1.1 joerg acquired, in order to prevent deadlock.
365 1.1 joerg
366 1.1 joerg .. code-block:: c++
367 1.1 joerg
368 1.1 joerg Mutex m1;
369 1.1 joerg Mutex m2 ACQUIRED_AFTER(m1);
370 1.1 joerg
371 1.1 joerg // Alternative declaration
372 1.1 joerg // Mutex m2;
373 1.1 joerg // Mutex m1 ACQUIRED_BEFORE(m2);
374 1.1 joerg
375 1.1 joerg void foo() {
376 1.1 joerg m2.Lock();
377 1.1 joerg m1.Lock(); // Warning! m2 must be acquired after m1.
378 1.1 joerg m1.Unlock();
379 1.1 joerg m2.Unlock();
380 1.1 joerg }
381 1.1 joerg
382 1.1 joerg
383 1.1 joerg CAPABILITY(<string>)
384 1.1 joerg --------------------
385 1.1 joerg
386 1.1 joerg *Previously*: ``LOCKABLE``
387 1.1 joerg
388 1.1 joerg ``CAPABILITY`` is an attribute on classes, which specifies that objects of the
389 1.1 joerg class can be used as a capability. The string argument specifies the kind of
390 1.1 joerg capability in error messages, e.g. ``"mutex"``. See the ``Container`` example
391 1.1 joerg given above, or the ``Mutex`` class in :ref:`mutexheader`.
392 1.1 joerg
393 1.1 joerg
394 1.1 joerg SCOPED_CAPABILITY
395 1.1 joerg -----------------
396 1.1 joerg
397 1.1 joerg *Previously*: ``SCOPED_LOCKABLE``
398 1.1 joerg
399 1.1 joerg ``SCOPED_CAPABILITY`` is an attribute on classes that implement RAII-style
400 1.1 joerg locking, in which a capability is acquired in the constructor, and released in
401 1.1 joerg the destructor. Such classes require special handling because the constructor
402 1.1 joerg and destructor refer to the capability via different names; see the
403 1.1 joerg ``MutexLocker`` class in :ref:`mutexheader`, below.
404 1.1 joerg
405 1.1 joerg
406 1.1 joerg TRY_ACQUIRE(<bool>, ...), TRY_ACQUIRE_SHARED(<bool>, ...)
407 1.1 joerg ---------------------------------------------------------
408 1.1 joerg
409 1.1 joerg *Previously:* ``EXCLUSIVE_TRYLOCK_FUNCTION``, ``SHARED_TRYLOCK_FUNCTION``
410 1.1 joerg
411 1.1 joerg These are attributes on a function or method that tries to acquire the given
412 1.1 joerg capability, and returns a boolean value indicating success or failure.
413 1.1 joerg The first argument must be ``true`` or ``false``, to specify which return value
414 1.1 joerg indicates success, and the remaining arguments are interpreted in the same way
415 1.1 joerg as ``ACQUIRE``. See :ref:`mutexheader`, below, for example uses.
416 1.1 joerg
417 1.1 joerg
418 1.1 joerg ASSERT_CAPABILITY(...) and ASSERT_SHARED_CAPABILITY(...)
419 1.1 joerg --------------------------------------------------------
420 1.1 joerg
421 1.1 joerg *Previously:* ``ASSERT_EXCLUSIVE_LOCK``, ``ASSERT_SHARED_LOCK``
422 1.1 joerg
423 1.1 joerg These are attributes on a function or method that does a run-time test to see
424 1.1 joerg whether the calling thread holds the given capability. The function is assumed
425 1.1 joerg to fail (no return) if the capability is not held. See :ref:`mutexheader`,
426 1.1 joerg below, for example uses.
427 1.1 joerg
428 1.1 joerg
429 1.1 joerg GUARDED_VAR and PT_GUARDED_VAR
430 1.1 joerg ------------------------------
431 1.1 joerg
432 1.1 joerg Use of these attributes has been deprecated.
433 1.1 joerg
434 1.1 joerg
435 1.1 joerg Warning flags
436 1.1 joerg -------------
437 1.1 joerg
438 1.1 joerg * ``-Wthread-safety``: Umbrella flag which turns on the following three:
439 1.1 joerg
440 1.1 joerg + ``-Wthread-safety-attributes``: Sanity checks on attribute syntax.
441 1.1 joerg + ``-Wthread-safety-analysis``: The core analysis.
442 1.1 joerg + ``-Wthread-safety-precise``: Requires that mutex expressions match precisely.
443 1.1 joerg This warning can be disabled for code which has a lot of aliases.
444 1.1 joerg + ``-Wthread-safety-reference``: Checks when guarded members are passed by reference.
445 1.1 joerg
446 1.1 joerg
447 1.1 joerg :ref:`negative` are an experimental feature, which are enabled with:
448 1.1 joerg
449 1.1 joerg * ``-Wthread-safety-negative``: Negative capabilities. Off by default.
450 1.1 joerg
451 1.1 joerg When new features and checks are added to the analysis, they can often introduce
452 1.1 joerg additional warnings. Those warnings are initially released as *beta* warnings
453 1.1 joerg for a period of time, after which they are migrated into the standard analysis.
454 1.1 joerg
455 1.1 joerg * ``-Wthread-safety-beta``: New features. Off by default.
456 1.1 joerg
457 1.1 joerg
458 1.1 joerg .. _negative:
459 1.1 joerg
460 1.1 joerg Negative Capabilities
461 1.1 joerg =====================
462 1.1 joerg
463 1.1 joerg Thread Safety Analysis is designed to prevent both race conditions and
464 1.1 joerg deadlock. The GUARDED_BY and REQUIRES attributes prevent race conditions, by
465 1.1 joerg ensuring that a capability is held before reading or writing to guarded data,
466 1.1 joerg and the EXCLUDES attribute prevents deadlock, by making sure that a mutex is
467 1.1 joerg *not* held.
468 1.1 joerg
469 1.1 joerg However, EXCLUDES is an optional attribute, and does not provide the same
470 1.1 joerg safety guarantee as REQUIRES. In particular:
471 1.1 joerg
472 1.1 joerg * A function which acquires a capability does not have to exclude it.
473 1.1 joerg * A function which calls a function that excludes a capability does not
474 1.1 joerg have transitively exclude that capability.
475 1.1 joerg
476 1.1 joerg As a result, EXCLUDES can easily produce false negatives:
477 1.1 joerg
478 1.1 joerg .. code-block:: c++
479 1.1 joerg
480 1.1 joerg class Foo {
481 1.1 joerg Mutex mu;
482 1.1 joerg
483 1.1 joerg void foo() {
484 1.1 joerg mu.Lock();
485 1.1 joerg bar(); // No warning.
486 1.1 joerg baz(); // No warning.
487 1.1 joerg mu.Unlock();
488 1.1 joerg }
489 1.1 joerg
490 1.1 joerg void bar() { // No warning. (Should have EXCLUDES(mu)).
491 1.1 joerg mu.Lock();
492 1.1 joerg // ...
493 1.1 joerg mu.Unlock();
494 1.1 joerg }
495 1.1 joerg
496 1.1 joerg void baz() {
497 1.1 joerg bif(); // No warning. (Should have EXCLUDES(mu)).
498 1.1 joerg }
499 1.1 joerg
500 1.1 joerg void bif() EXCLUDES(mu);
501 1.1 joerg };
502 1.1 joerg
503 1.1 joerg
504 1.1 joerg Negative requirements are an alternative EXCLUDES that provide
505 1.1 joerg a stronger safety guarantee. A negative requirement uses the REQUIRES
506 1.1 joerg attribute, in conjunction with the ``!`` operator, to indicate that a capability
507 1.1 joerg should *not* be held.
508 1.1 joerg
509 1.1 joerg For example, using ``REQUIRES(!mu)`` instead of ``EXCLUDES(mu)`` will produce
510 1.1 joerg the appropriate warnings:
511 1.1 joerg
512 1.1 joerg .. code-block:: c++
513 1.1 joerg
514 1.1 joerg class FooNeg {
515 1.1 joerg Mutex mu;
516 1.1 joerg
517 1.1 joerg void foo() REQUIRES(!mu) { // foo() now requires !mu.
518 1.1 joerg mu.Lock();
519 1.1 joerg bar();
520 1.1 joerg baz();
521 1.1 joerg mu.Unlock();
522 1.1 joerg }
523 1.1 joerg
524 1.1 joerg void bar() {
525 1.1 joerg mu.Lock(); // WARNING! Missing REQUIRES(!mu).
526 1.1 joerg // ...
527 1.1 joerg mu.Unlock();
528 1.1 joerg }
529 1.1 joerg
530 1.1 joerg void baz() {
531 1.1 joerg bif(); // WARNING! Missing REQUIRES(!mu).
532 1.1 joerg }
533 1.1 joerg
534 1.1 joerg void bif() REQUIRES(!mu);
535 1.1 joerg };
536 1.1 joerg
537 1.1 joerg
538 1.1 joerg Negative requirements are an experimental feature which is off by default,
539 1.1 joerg because it will produce many warnings in existing code. It can be enabled
540 1.1 joerg by passing ``-Wthread-safety-negative``.
541 1.1 joerg
542 1.1 joerg
543 1.1 joerg .. _faq:
544 1.1 joerg
545 1.1 joerg Frequently Asked Questions
546 1.1 joerg ==========================
547 1.1 joerg
548 1.1 joerg (Q) Should I put attributes in the header file, or in the .cc/.cpp/.cxx file?
549 1.1 joerg
550 1.1 joerg (A) Attributes are part of the formal interface of a function, and should
551 1.1 joerg always go in the header, where they are visible to anything that includes
552 1.1 joerg the header. Attributes in the .cpp file are not visible outside of the
553 1.1 joerg immediate translation unit, which leads to false negatives and false positives.
554 1.1 joerg
555 1.1 joerg
556 1.1 joerg (Q) "*Mutex is not locked on every path through here?*" What does that mean?
557 1.1 joerg
558 1.1 joerg (A) See :ref:`conditional_locks`, below.
559 1.1 joerg
560 1.1 joerg
561 1.1 joerg .. _limitations:
562 1.1 joerg
563 1.1 joerg Known Limitations
564 1.1 joerg =================
565 1.1 joerg
566 1.1 joerg Lexical scope
567 1.1 joerg -------------
568 1.1 joerg
569 1.1 joerg Thread safety attributes contain ordinary C++ expressions, and thus follow
570 1.1 joerg ordinary C++ scoping rules. In particular, this means that mutexes and other
571 1.1 joerg capabilities must be declared before they can be used in an attribute.
572 1.1 joerg Use-before-declaration is okay within a single class, because attributes are
573 1.1 joerg parsed at the same time as method bodies. (C++ delays parsing of method bodies
574 1.1 joerg until the end of the class.) However, use-before-declaration is not allowed
575 1.1 joerg between classes, as illustrated below.
576 1.1 joerg
577 1.1 joerg .. code-block:: c++
578 1.1 joerg
579 1.1 joerg class Foo;
580 1.1 joerg
581 1.1 joerg class Bar {
582 1.1 joerg void bar(Foo* f) REQUIRES(f->mu); // Error: mu undeclared.
583 1.1 joerg };
584 1.1 joerg
585 1.1 joerg class Foo {
586 1.1 joerg Mutex mu;
587 1.1 joerg };
588 1.1 joerg
589 1.1 joerg
590 1.1 joerg Private Mutexes
591 1.1 joerg ---------------
592 1.1 joerg
593 1.1 joerg Good software engineering practice dictates that mutexes should be private
594 1.1 joerg members, because the locking mechanism used by a thread-safe class is part of
595 1.1 joerg its internal implementation. However, private mutexes can sometimes leak into
596 1.1 joerg the public interface of a class.
597 1.1 joerg Thread safety attributes follow normal C++ access restrictions, so if ``mu``
598 1.1 joerg is a private member of ``c``, then it is an error to write ``c.mu`` in an
599 1.1 joerg attribute.
600 1.1 joerg
601 1.1 joerg One workaround is to (ab)use the ``RETURN_CAPABILITY`` attribute to provide a
602 1.1 joerg public *name* for a private mutex, without actually exposing the underlying
603 1.1 joerg mutex. For example:
604 1.1 joerg
605 1.1 joerg .. code-block:: c++
606 1.1 joerg
607 1.1 joerg class MyClass {
608 1.1 joerg private:
609 1.1 joerg Mutex mu;
610 1.1 joerg
611 1.1 joerg public:
612 1.1 joerg // For thread safety analysis only. Does not actually return mu.
613 1.1 joerg Mutex* getMu() RETURN_CAPABILITY(mu) { return 0; }
614 1.1 joerg
615 1.1 joerg void doSomething() REQUIRES(mu);
616 1.1 joerg };
617 1.1 joerg
618 1.1 joerg void doSomethingTwice(MyClass& c) REQUIRES(c.getMu()) {
619 1.1 joerg // The analysis thinks that c.getMu() == c.mu
620 1.1 joerg c.doSomething();
621 1.1 joerg c.doSomething();
622 1.1 joerg }
623 1.1 joerg
624 1.1 joerg In the above example, ``doSomethingTwice()`` is an external routine that
625 1.1 joerg requires ``c.mu`` to be locked, which cannot be declared directly because ``mu``
626 1.1 joerg is private. This pattern is discouraged because it
627 1.1 joerg violates encapsulation, but it is sometimes necessary, especially when adding
628 1.1 joerg annotations to an existing code base. The workaround is to define ``getMu()``
629 1.1 joerg as a fake getter method, which is provided only for the benefit of thread
630 1.1 joerg safety analysis.
631 1.1 joerg
632 1.1 joerg
633 1.1 joerg .. _conditional_locks:
634 1.1 joerg
635 1.1 joerg No conditionally held locks.
636 1.1 joerg ----------------------------
637 1.1 joerg
638 1.1 joerg The analysis must be able to determine whether a lock is held, or not held, at
639 1.1 joerg every program point. Thus, sections of code where a lock *might be held* will
640 1.1 joerg generate spurious warnings (false positives). For example:
641 1.1 joerg
642 1.1 joerg .. code-block:: c++
643 1.1 joerg
644 1.1 joerg void foo() {
645 1.1 joerg bool b = needsToLock();
646 1.1 joerg if (b) mu.Lock();
647 1.1 joerg ... // Warning! Mutex 'mu' is not held on every path through here.
648 1.1 joerg if (b) mu.Unlock();
649 1.1 joerg }
650 1.1 joerg
651 1.1 joerg
652 1.1 joerg No checking inside constructors and destructors.
653 1.1 joerg ------------------------------------------------
654 1.1 joerg
655 1.1 joerg The analysis currently does not do any checking inside constructors or
656 1.1 joerg destructors. In other words, every constructor and destructor is treated as
657 1.1 joerg if it was annotated with ``NO_THREAD_SAFETY_ANALYSIS``.
658 1.1 joerg The reason for this is that during initialization, only one thread typically
659 1.1 joerg has access to the object which is being initialized, and it is thus safe (and
660 1.1 joerg common practice) to initialize guarded members without acquiring any locks.
661 1.1 joerg The same is true of destructors.
662 1.1 joerg
663 1.1 joerg Ideally, the analysis would allow initialization of guarded members inside the
664 1.1 joerg object being initialized or destroyed, while still enforcing the usual access
665 1.1 joerg restrictions on everything else. However, this is difficult to enforce in
666 1.1 joerg practice, because in complex pointer-based data structures, it is hard to
667 1.1 joerg determine what data is owned by the enclosing object.
668 1.1 joerg
669 1.1 joerg No inlining.
670 1.1 joerg ------------
671 1.1 joerg
672 1.1 joerg Thread safety analysis is strictly intra-procedural, just like ordinary type
673 1.1 joerg checking. It relies only on the declared attributes of a function, and will
674 1.1 joerg not attempt to inline any method calls. As a result, code such as the
675 1.1 joerg following will not work:
676 1.1 joerg
677 1.1 joerg .. code-block:: c++
678 1.1 joerg
679 1.1 joerg template<class T>
680 1.1 joerg class AutoCleanup {
681 1.1 joerg T* object;
682 1.1 joerg void (T::*mp)();
683 1.1 joerg
684 1.1 joerg public:
685 1.1 joerg AutoCleanup(T* obj, void (T::*imp)()) : object(obj), mp(imp) { }
686 1.1 joerg ~AutoCleanup() { (object->*mp)(); }
687 1.1 joerg };
688 1.1 joerg
689 1.1 joerg Mutex mu;
690 1.1 joerg void foo() {
691 1.1 joerg mu.Lock();
692 1.1 joerg AutoCleanup<Mutex>(&mu, &Mutex::Unlock);
693 1.1 joerg // ...
694 1.1 joerg } // Warning, mu is not unlocked.
695 1.1 joerg
696 1.1 joerg In this case, the destructor of ``Autocleanup`` calls ``mu.Unlock()``, so
697 1.1 joerg the warning is bogus. However,
698 1.1 joerg thread safety analysis cannot see the unlock, because it does not attempt to
699 1.1 joerg inline the destructor. Moreover, there is no way to annotate the destructor,
700 1.1 joerg because the destructor is calling a function that is not statically known.
701 1.1 joerg This pattern is simply not supported.
702 1.1 joerg
703 1.1 joerg
704 1.1 joerg No alias analysis.
705 1.1 joerg ------------------
706 1.1 joerg
707 1.1 joerg The analysis currently does not track pointer aliases. Thus, there can be
708 1.1 joerg false positives if two pointers both point to the same mutex.
709 1.1 joerg
710 1.1 joerg
711 1.1 joerg .. code-block:: c++
712 1.1 joerg
713 1.1 joerg class MutexUnlocker {
714 1.1 joerg Mutex* mu;
715 1.1 joerg
716 1.1 joerg public:
717 1.1 joerg MutexUnlocker(Mutex* m) RELEASE(m) : mu(m) { mu->Unlock(); }
718 1.1 joerg ~MutexUnlocker() ACQUIRE(mu) { mu->Lock(); }
719 1.1 joerg };
720 1.1 joerg
721 1.1 joerg Mutex mutex;
722 1.1 joerg void test() REQUIRES(mutex) {
723 1.1 joerg {
724 1.1 joerg MutexUnlocker munl(&mutex); // unlocks mutex
725 1.1 joerg doSomeIO();
726 1.1 joerg } // Warning: locks munl.mu
727 1.1 joerg }
728 1.1 joerg
729 1.1 joerg The MutexUnlocker class is intended to be the dual of the MutexLocker class,
730 1.1 joerg defined in :ref:`mutexheader`. However, it doesn't work because the analysis
731 1.1 joerg doesn't know that munl.mu == mutex. The SCOPED_CAPABILITY attribute handles
732 1.1 joerg aliasing for MutexLocker, but does so only for that particular pattern.
733 1.1 joerg
734 1.1 joerg
735 1.1 joerg ACQUIRED_BEFORE(...) and ACQUIRED_AFTER(...) are currently unimplemented.
736 1.1 joerg -------------------------------------------------------------------------
737 1.1 joerg
738 1.1 joerg To be fixed in a future update.
739 1.1 joerg
740 1.1 joerg
741 1.1 joerg .. _mutexheader:
742 1.1 joerg
743 1.1 joerg mutex.h
744 1.1 joerg =======
745 1.1 joerg
746 1.1 joerg Thread safety analysis can be used with any threading library, but it does
747 1.1 joerg require that the threading API be wrapped in classes and methods which have the
748 1.1 joerg appropriate annotations. The following code provides ``mutex.h`` as an example;
749 1.1 joerg these methods should be filled in to call the appropriate underlying
750 1.1 joerg implementation.
751 1.1 joerg
752 1.1 joerg
753 1.1 joerg .. code-block:: c++
754 1.1 joerg
755 1.1 joerg
756 1.1 joerg #ifndef THREAD_SAFETY_ANALYSIS_MUTEX_H
757 1.1 joerg #define THREAD_SAFETY_ANALYSIS_MUTEX_H
758 1.1 joerg
759 1.1 joerg // Enable thread safety attributes only with clang.
760 1.1 joerg // The attributes can be safely erased when compiling with other compilers.
761 1.1 joerg #if defined(__clang__) && (!defined(SWIG))
762 1.1 joerg #define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
763 1.1 joerg #else
764 1.1 joerg #define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op
765 1.1 joerg #endif
766 1.1 joerg
767 1.1 joerg #define CAPABILITY(x) \
768 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(capability(x))
769 1.1 joerg
770 1.1 joerg #define SCOPED_CAPABILITY \
771 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
772 1.1 joerg
773 1.1 joerg #define GUARDED_BY(x) \
774 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
775 1.1 joerg
776 1.1 joerg #define PT_GUARDED_BY(x) \
777 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))
778 1.1 joerg
779 1.1 joerg #define ACQUIRED_BEFORE(...) \
780 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__))
781 1.1 joerg
782 1.1 joerg #define ACQUIRED_AFTER(...) \
783 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__))
784 1.1 joerg
785 1.1 joerg #define REQUIRES(...) \
786 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__))
787 1.1 joerg
788 1.1 joerg #define REQUIRES_SHARED(...) \
789 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__))
790 1.1 joerg
791 1.1 joerg #define ACQUIRE(...) \
792 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__))
793 1.1 joerg
794 1.1 joerg #define ACQUIRE_SHARED(...) \
795 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__))
796 1.1 joerg
797 1.1 joerg #define RELEASE(...) \
798 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__))
799 1.1 joerg
800 1.1 joerg #define RELEASE_SHARED(...) \
801 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__))
802 1.1 joerg
803 1.1 joerg #define TRY_ACQUIRE(...) \
804 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__))
805 1.1 joerg
806 1.1 joerg #define TRY_ACQUIRE_SHARED(...) \
807 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__))
808 1.1 joerg
809 1.1 joerg #define EXCLUDES(...) \
810 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
811 1.1 joerg
812 1.1 joerg #define ASSERT_CAPABILITY(x) \
813 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x))
814 1.1 joerg
815 1.1 joerg #define ASSERT_SHARED_CAPABILITY(x) \
816 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x))
817 1.1 joerg
818 1.1 joerg #define RETURN_CAPABILITY(x) \
819 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
820 1.1 joerg
821 1.1 joerg #define NO_THREAD_SAFETY_ANALYSIS \
822 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
823 1.1 joerg
824 1.1 joerg
825 1.1 joerg // Defines an annotated interface for mutexes.
826 1.1 joerg // These methods can be implemented to use any internal mutex implementation.
827 1.1 joerg class CAPABILITY("mutex") Mutex {
828 1.1 joerg public:
829 1.1 joerg // Acquire/lock this mutex exclusively. Only one thread can have exclusive
830 1.1 joerg // access at any one time. Write operations to guarded data require an
831 1.1 joerg // exclusive lock.
832 1.1 joerg void Lock() ACQUIRE();
833 1.1 joerg
834 1.1 joerg // Acquire/lock this mutex for read operations, which require only a shared
835 1.1 joerg // lock. This assumes a multiple-reader, single writer semantics. Multiple
836 1.1 joerg // threads may acquire the mutex simultaneously as readers, but a writer
837 1.1 joerg // must wait for all of them to release the mutex before it can acquire it
838 1.1 joerg // exclusively.
839 1.1 joerg void ReaderLock() ACQUIRE_SHARED();
840 1.1 joerg
841 1.1 joerg // Release/unlock an exclusive mutex.
842 1.1 joerg void Unlock() RELEASE();
843 1.1 joerg
844 1.1 joerg // Release/unlock a shared mutex.
845 1.1 joerg void ReaderUnlock() RELEASE_SHARED();
846 1.1 joerg
847 1.1 joerg // Try to acquire the mutex. Returns true on success, and false on failure.
848 1.1 joerg bool TryLock() TRY_ACQUIRE(true);
849 1.1 joerg
850 1.1 joerg // Try to acquire the mutex for read operations.
851 1.1 joerg bool ReaderTryLock() TRY_ACQUIRE_SHARED(true);
852 1.1 joerg
853 1.1 joerg // Assert that this mutex is currently held by the calling thread.
854 1.1 joerg void AssertHeld() ASSERT_CAPABILITY(this);
855 1.1 joerg
856 1.1 joerg // Assert that is mutex is currently held for read operations.
857 1.1 joerg void AssertReaderHeld() ASSERT_SHARED_CAPABILITY(this);
858 1.1 joerg
859 1.1 joerg // For negative capabilities.
860 1.1 joerg const Mutex& operator!() const { return *this; }
861 1.1 joerg };
862 1.1 joerg
863 1.1 joerg
864 1.1 joerg // MutexLocker is an RAII class that acquires a mutex in its constructor, and
865 1.1 joerg // releases it in its destructor.
866 1.1 joerg class SCOPED_CAPABILITY MutexLocker {
867 1.1 joerg private:
868 1.1 joerg Mutex* mut;
869 1.1 joerg
870 1.1 joerg public:
871 1.1 joerg MutexLocker(Mutex *mu) ACQUIRE(mu) : mut(mu) {
872 1.1 joerg mu->Lock();
873 1.1 joerg }
874 1.1 joerg ~MutexLocker() RELEASE() {
875 1.1 joerg mut->Unlock();
876 1.1 joerg }
877 1.1 joerg };
878 1.1 joerg
879 1.1 joerg
880 1.1 joerg #ifdef USE_LOCK_STYLE_THREAD_SAFETY_ATTRIBUTES
881 1.1 joerg // The original version of thread safety analysis the following attribute
882 1.1 joerg // definitions. These use a lock-based terminology. They are still in use
883 1.1 joerg // by existing thread safety code, and will continue to be supported.
884 1.1 joerg
885 1.1 joerg // Deprecated.
886 1.1 joerg #define PT_GUARDED_VAR \
887 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_var)
888 1.1 joerg
889 1.1 joerg // Deprecated.
890 1.1 joerg #define GUARDED_VAR \
891 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(guarded_var)
892 1.1 joerg
893 1.1 joerg // Replaced by REQUIRES
894 1.1 joerg #define EXCLUSIVE_LOCKS_REQUIRED(...) \
895 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__))
896 1.1 joerg
897 1.1 joerg // Replaced by REQUIRES_SHARED
898 1.1 joerg #define SHARED_LOCKS_REQUIRED(...) \
899 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(__VA_ARGS__))
900 1.1 joerg
901 1.1 joerg // Replaced by CAPABILITY
902 1.1 joerg #define LOCKABLE \
903 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(lockable)
904 1.1 joerg
905 1.1 joerg // Replaced by SCOPED_CAPABILITY
906 1.1 joerg #define SCOPED_LOCKABLE \
907 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
908 1.1 joerg
909 1.1 joerg // Replaced by ACQUIRE
910 1.1 joerg #define EXCLUSIVE_LOCK_FUNCTION(...) \
911 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(__VA_ARGS__))
912 1.1 joerg
913 1.1 joerg // Replaced by ACQUIRE_SHARED
914 1.1 joerg #define SHARED_LOCK_FUNCTION(...) \
915 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(shared_lock_function(__VA_ARGS__))
916 1.1 joerg
917 1.1 joerg // Replaced by RELEASE and RELEASE_SHARED
918 1.1 joerg #define UNLOCK_FUNCTION(...) \
919 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(__VA_ARGS__))
920 1.1 joerg
921 1.1 joerg // Replaced by TRY_ACQUIRE
922 1.1 joerg #define EXCLUSIVE_TRYLOCK_FUNCTION(...) \
923 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock_function(__VA_ARGS__))
924 1.1 joerg
925 1.1 joerg // Replaced by TRY_ACQUIRE_SHARED
926 1.1 joerg #define SHARED_TRYLOCK_FUNCTION(...) \
927 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock_function(__VA_ARGS__))
928 1.1 joerg
929 1.1 joerg // Replaced by ASSERT_CAPABILITY
930 1.1 joerg #define ASSERT_EXCLUSIVE_LOCK(...) \
931 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(assert_exclusive_lock(__VA_ARGS__))
932 1.1 joerg
933 1.1 joerg // Replaced by ASSERT_SHARED_CAPABILITY
934 1.1 joerg #define ASSERT_SHARED_LOCK(...) \
935 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_lock(__VA_ARGS__))
936 1.1 joerg
937 1.1 joerg // Replaced by EXCLUDE_CAPABILITY.
938 1.1 joerg #define LOCKS_EXCLUDED(...) \
939 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
940 1.1 joerg
941 1.1 joerg // Replaced by RETURN_CAPABILITY
942 1.1 joerg #define LOCK_RETURNED(x) \
943 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
944 1.1 joerg
945 1.1 joerg #endif // USE_LOCK_STYLE_THREAD_SAFETY_ATTRIBUTES
946 1.1 joerg
947 1.1 joerg #endif // THREAD_SAFETY_ANALYSIS_MUTEX_H
948 1.1 joerg
949