ThreadSafetyAnalysis.rst revision 1.1.1.2 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.1.2 joerg The attributes only control assumptions made by thread safety analysis and the
148 1.1.1.2 joerg warnings it issues. They don't affect generated code or behavior at run-time.
149 1.1.1.2 joerg
150 1.1 joerg For historical reasons, prior versions of thread safety used macro names that
151 1.1 joerg were very lock-centric. These macros have since been renamed to fit a more
152 1.1 joerg general capability model. The prior names are still in use, and will be
153 1.1 joerg mentioned under the tag *previously* where appropriate.
154 1.1 joerg
155 1.1 joerg
156 1.1 joerg GUARDED_BY(c) and PT_GUARDED_BY(c)
157 1.1 joerg ----------------------------------
158 1.1 joerg
159 1.1 joerg ``GUARDED_BY`` is an attribute on data members, which declares that the data
160 1.1 joerg member is protected by the given capability. Read operations on the data
161 1.1 joerg require shared access, while write operations require exclusive access.
162 1.1 joerg
163 1.1 joerg ``PT_GUARDED_BY`` is similar, but is intended for use on pointers and smart
164 1.1 joerg pointers. There is no constraint on the data member itself, but the *data that
165 1.1 joerg it points to* is protected by the given capability.
166 1.1 joerg
167 1.1 joerg .. code-block:: c++
168 1.1 joerg
169 1.1 joerg Mutex mu;
170 1.1 joerg int *p1 GUARDED_BY(mu);
171 1.1 joerg int *p2 PT_GUARDED_BY(mu);
172 1.1 joerg unique_ptr<int> p3 PT_GUARDED_BY(mu);
173 1.1 joerg
174 1.1 joerg void test() {
175 1.1 joerg p1 = 0; // Warning!
176 1.1 joerg
177 1.1 joerg *p2 = 42; // Warning!
178 1.1 joerg p2 = new int; // OK.
179 1.1 joerg
180 1.1 joerg *p3 = 42; // Warning!
181 1.1 joerg p3.reset(new int); // OK.
182 1.1 joerg }
183 1.1 joerg
184 1.1 joerg
185 1.1 joerg REQUIRES(...), REQUIRES_SHARED(...)
186 1.1 joerg -----------------------------------
187 1.1 joerg
188 1.1 joerg *Previously*: ``EXCLUSIVE_LOCKS_REQUIRED``, ``SHARED_LOCKS_REQUIRED``
189 1.1 joerg
190 1.1 joerg ``REQUIRES`` is an attribute on functions or methods, which
191 1.1 joerg declares that the calling thread must have exclusive access to the given
192 1.1 joerg capabilities. More than one capability may be specified. The capabilities
193 1.1 joerg must be held on entry to the function, *and must still be held on exit*.
194 1.1 joerg
195 1.1 joerg ``REQUIRES_SHARED`` is similar, but requires only shared access.
196 1.1 joerg
197 1.1 joerg .. code-block:: c++
198 1.1 joerg
199 1.1 joerg Mutex mu1, mu2;
200 1.1 joerg int a GUARDED_BY(mu1);
201 1.1 joerg int b GUARDED_BY(mu2);
202 1.1 joerg
203 1.1 joerg void foo() REQUIRES(mu1, mu2) {
204 1.1 joerg a = 0;
205 1.1 joerg b = 0;
206 1.1 joerg }
207 1.1 joerg
208 1.1 joerg void test() {
209 1.1 joerg mu1.Lock();
210 1.1 joerg foo(); // Warning! Requires mu2.
211 1.1 joerg mu1.Unlock();
212 1.1 joerg }
213 1.1 joerg
214 1.1 joerg
215 1.1.1.2 joerg ACQUIRE(...), ACQUIRE_SHARED(...), RELEASE(...), RELEASE_SHARED(...), RELEASE_GENERIC(...)
216 1.1.1.2 joerg ------------------------------------------------------------------------------------------
217 1.1 joerg
218 1.1 joerg *Previously*: ``EXCLUSIVE_LOCK_FUNCTION``, ``SHARED_LOCK_FUNCTION``,
219 1.1 joerg ``UNLOCK_FUNCTION``
220 1.1 joerg
221 1.1.1.2 joerg ``ACQUIRE`` and ``ACQUIRE_SHARED`` are attributes on functions or methods
222 1.1.1.2 joerg declaring that the function acquires a capability, but does not release it.
223 1.1.1.2 joerg The given capability must not be held on entry, and will be held on exit
224 1.1.1.2 joerg (exclusively for ``ACQUIRE``, shared for ``ACQUIRE_SHARED``).
225 1.1.1.2 joerg
226 1.1.1.2 joerg ``RELEASE``, ``RELEASE_SHARED``, and ``RELEASE_GENERIC`` declare that the
227 1.1.1.2 joerg function releases the given capability. The capability must be held on entry
228 1.1.1.2 joerg (exclusively for ``RELEASE``, shared for ``RELEASE_SHARED``, exclusively or
229 1.1.1.2 joerg shared for ``RELEASE_GENERIC``), and will no longer be held on exit.
230 1.1 joerg
231 1.1 joerg .. code-block:: c++
232 1.1 joerg
233 1.1 joerg Mutex mu;
234 1.1 joerg MyClass myObject GUARDED_BY(mu);
235 1.1 joerg
236 1.1 joerg void lockAndInit() ACQUIRE(mu) {
237 1.1 joerg mu.Lock();
238 1.1 joerg myObject.init();
239 1.1 joerg }
240 1.1 joerg
241 1.1 joerg void cleanupAndUnlock() RELEASE(mu) {
242 1.1 joerg myObject.cleanup();
243 1.1 joerg } // Warning! Need to unlock mu.
244 1.1 joerg
245 1.1 joerg void test() {
246 1.1 joerg lockAndInit();
247 1.1 joerg myObject.doSomething();
248 1.1 joerg cleanupAndUnlock();
249 1.1 joerg myObject.doSomething(); // Warning, mu is not locked.
250 1.1 joerg }
251 1.1 joerg
252 1.1 joerg If no argument is passed to ``ACQUIRE`` or ``RELEASE``, then the argument is
253 1.1 joerg assumed to be ``this``, and the analysis will not check the body of the
254 1.1 joerg function. This pattern is intended for use by classes which hide locking
255 1.1 joerg details behind an abstract interface. For example:
256 1.1 joerg
257 1.1 joerg .. code-block:: c++
258 1.1 joerg
259 1.1 joerg template <class T>
260 1.1 joerg class CAPABILITY("mutex") Container {
261 1.1 joerg private:
262 1.1 joerg Mutex mu;
263 1.1 joerg T* data;
264 1.1 joerg
265 1.1 joerg public:
266 1.1 joerg // Hide mu from public interface.
267 1.1 joerg void Lock() ACQUIRE() { mu.Lock(); }
268 1.1 joerg void Unlock() RELEASE() { mu.Unlock(); }
269 1.1 joerg
270 1.1 joerg T& getElem(int i) { return data[i]; }
271 1.1 joerg };
272 1.1 joerg
273 1.1 joerg void test() {
274 1.1 joerg Container<int> c;
275 1.1 joerg c.Lock();
276 1.1 joerg int i = c.getElem(0);
277 1.1 joerg c.Unlock();
278 1.1 joerg }
279 1.1 joerg
280 1.1 joerg
281 1.1 joerg EXCLUDES(...)
282 1.1 joerg -------------
283 1.1 joerg
284 1.1 joerg *Previously*: ``LOCKS_EXCLUDED``
285 1.1 joerg
286 1.1 joerg ``EXCLUDES`` is an attribute on functions or methods, which declares that
287 1.1 joerg the caller must *not* hold the given capabilities. This annotation is
288 1.1 joerg used to prevent deadlock. Many mutex implementations are not re-entrant, so
289 1.1 joerg deadlock can occur if the function acquires the mutex a second time.
290 1.1 joerg
291 1.1 joerg .. code-block:: c++
292 1.1 joerg
293 1.1 joerg Mutex mu;
294 1.1 joerg int a GUARDED_BY(mu);
295 1.1 joerg
296 1.1 joerg void clear() EXCLUDES(mu) {
297 1.1 joerg mu.Lock();
298 1.1 joerg a = 0;
299 1.1 joerg mu.Unlock();
300 1.1 joerg }
301 1.1 joerg
302 1.1 joerg void reset() {
303 1.1 joerg mu.Lock();
304 1.1 joerg clear(); // Warning! Caller cannot hold 'mu'.
305 1.1 joerg mu.Unlock();
306 1.1 joerg }
307 1.1 joerg
308 1.1 joerg Unlike ``REQUIRES``, ``EXCLUDES`` is optional. The analysis will not issue a
309 1.1 joerg warning if the attribute is missing, which can lead to false negatives in some
310 1.1 joerg cases. This issue is discussed further in :ref:`negative`.
311 1.1 joerg
312 1.1 joerg
313 1.1 joerg NO_THREAD_SAFETY_ANALYSIS
314 1.1 joerg -------------------------
315 1.1 joerg
316 1.1 joerg ``NO_THREAD_SAFETY_ANALYSIS`` is an attribute on functions or methods, which
317 1.1 joerg turns off thread safety checking for that method. It provides an escape hatch
318 1.1 joerg for functions which are either (1) deliberately thread-unsafe, or (2) are
319 1.1 joerg thread-safe, but too complicated for the analysis to understand. Reasons for
320 1.1 joerg (2) will be described in the :ref:`limitations`, below.
321 1.1 joerg
322 1.1 joerg .. code-block:: c++
323 1.1 joerg
324 1.1 joerg class Counter {
325 1.1 joerg Mutex mu;
326 1.1 joerg int a GUARDED_BY(mu);
327 1.1 joerg
328 1.1 joerg void unsafeIncrement() NO_THREAD_SAFETY_ANALYSIS { a++; }
329 1.1 joerg };
330 1.1 joerg
331 1.1 joerg Unlike the other attributes, NO_THREAD_SAFETY_ANALYSIS is not part of the
332 1.1 joerg interface of a function, and should thus be placed on the function definition
333 1.1 joerg (in the ``.cc`` or ``.cpp`` file) rather than on the function declaration
334 1.1 joerg (in the header).
335 1.1 joerg
336 1.1 joerg
337 1.1 joerg RETURN_CAPABILITY(c)
338 1.1 joerg --------------------
339 1.1 joerg
340 1.1 joerg *Previously*: ``LOCK_RETURNED``
341 1.1 joerg
342 1.1 joerg ``RETURN_CAPABILITY`` is an attribute on functions or methods, which declares
343 1.1 joerg that the function returns a reference to the given capability. It is used to
344 1.1 joerg annotate getter methods that return mutexes.
345 1.1 joerg
346 1.1 joerg .. code-block:: c++
347 1.1 joerg
348 1.1 joerg class MyClass {
349 1.1 joerg private:
350 1.1 joerg Mutex mu;
351 1.1 joerg int a GUARDED_BY(mu);
352 1.1 joerg
353 1.1 joerg public:
354 1.1 joerg Mutex* getMu() RETURN_CAPABILITY(mu) { return μ }
355 1.1 joerg
356 1.1 joerg // analysis knows that getMu() == mu
357 1.1 joerg void clear() REQUIRES(getMu()) { a = 0; }
358 1.1 joerg };
359 1.1 joerg
360 1.1 joerg
361 1.1 joerg ACQUIRED_BEFORE(...), ACQUIRED_AFTER(...)
362 1.1 joerg -----------------------------------------
363 1.1 joerg
364 1.1 joerg ``ACQUIRED_BEFORE`` and ``ACQUIRED_AFTER`` are attributes on member
365 1.1 joerg declarations, specifically declarations of mutexes or other capabilities.
366 1.1 joerg These declarations enforce a particular order in which the mutexes must be
367 1.1 joerg acquired, in order to prevent deadlock.
368 1.1 joerg
369 1.1 joerg .. code-block:: c++
370 1.1 joerg
371 1.1 joerg Mutex m1;
372 1.1 joerg Mutex m2 ACQUIRED_AFTER(m1);
373 1.1 joerg
374 1.1 joerg // Alternative declaration
375 1.1 joerg // Mutex m2;
376 1.1 joerg // Mutex m1 ACQUIRED_BEFORE(m2);
377 1.1 joerg
378 1.1 joerg void foo() {
379 1.1 joerg m2.Lock();
380 1.1 joerg m1.Lock(); // Warning! m2 must be acquired after m1.
381 1.1 joerg m1.Unlock();
382 1.1 joerg m2.Unlock();
383 1.1 joerg }
384 1.1 joerg
385 1.1 joerg
386 1.1 joerg CAPABILITY(<string>)
387 1.1 joerg --------------------
388 1.1 joerg
389 1.1 joerg *Previously*: ``LOCKABLE``
390 1.1 joerg
391 1.1 joerg ``CAPABILITY`` is an attribute on classes, which specifies that objects of the
392 1.1 joerg class can be used as a capability. The string argument specifies the kind of
393 1.1 joerg capability in error messages, e.g. ``"mutex"``. See the ``Container`` example
394 1.1 joerg given above, or the ``Mutex`` class in :ref:`mutexheader`.
395 1.1 joerg
396 1.1 joerg
397 1.1 joerg SCOPED_CAPABILITY
398 1.1 joerg -----------------
399 1.1 joerg
400 1.1 joerg *Previously*: ``SCOPED_LOCKABLE``
401 1.1 joerg
402 1.1 joerg ``SCOPED_CAPABILITY`` is an attribute on classes that implement RAII-style
403 1.1 joerg locking, in which a capability is acquired in the constructor, and released in
404 1.1 joerg the destructor. Such classes require special handling because the constructor
405 1.1 joerg and destructor refer to the capability via different names; see the
406 1.1 joerg ``MutexLocker`` class in :ref:`mutexheader`, below.
407 1.1 joerg
408 1.1.1.2 joerg Scoped capabilities are treated as capabilities that are implicitly acquired
409 1.1.1.2 joerg on construction and released on destruction. They are associated with
410 1.1.1.2 joerg the set of (regular) capabilities named in thread safety attributes on the
411 1.1.1.2 joerg constructor. Acquire-type attributes on other member functions are treated as
412 1.1.1.2 joerg applying to that set of associated capabilities, while ``RELEASE`` implies that
413 1.1.1.2 joerg a function releases all associated capabilities in whatever mode they're held.
414 1.1.1.2 joerg
415 1.1 joerg
416 1.1 joerg TRY_ACQUIRE(<bool>, ...), TRY_ACQUIRE_SHARED(<bool>, ...)
417 1.1 joerg ---------------------------------------------------------
418 1.1 joerg
419 1.1 joerg *Previously:* ``EXCLUSIVE_TRYLOCK_FUNCTION``, ``SHARED_TRYLOCK_FUNCTION``
420 1.1 joerg
421 1.1 joerg These are attributes on a function or method that tries to acquire the given
422 1.1 joerg capability, and returns a boolean value indicating success or failure.
423 1.1 joerg The first argument must be ``true`` or ``false``, to specify which return value
424 1.1 joerg indicates success, and the remaining arguments are interpreted in the same way
425 1.1 joerg as ``ACQUIRE``. See :ref:`mutexheader`, below, for example uses.
426 1.1 joerg
427 1.1.1.2 joerg Because the analysis doesn't support conditional locking, a capability is
428 1.1.1.2 joerg treated as acquired after the first branch on the return value of a try-acquire
429 1.1.1.2 joerg function.
430 1.1.1.2 joerg
431 1.1.1.2 joerg .. code-block:: c++
432 1.1.1.2 joerg
433 1.1.1.2 joerg Mutex mu;
434 1.1.1.2 joerg int a GUARDED_BY(mu);
435 1.1.1.2 joerg
436 1.1.1.2 joerg void foo() {
437 1.1.1.2 joerg bool success = mu.TryLock();
438 1.1.1.2 joerg a = 0; // Warning, mu is not locked.
439 1.1.1.2 joerg if (success) {
440 1.1.1.2 joerg a = 0; // Ok.
441 1.1.1.2 joerg mu.Unlock();
442 1.1.1.2 joerg } else {
443 1.1.1.2 joerg a = 0; // Warning, mu is not locked.
444 1.1.1.2 joerg }
445 1.1.1.2 joerg }
446 1.1.1.2 joerg
447 1.1 joerg
448 1.1 joerg ASSERT_CAPABILITY(...) and ASSERT_SHARED_CAPABILITY(...)
449 1.1 joerg --------------------------------------------------------
450 1.1 joerg
451 1.1 joerg *Previously:* ``ASSERT_EXCLUSIVE_LOCK``, ``ASSERT_SHARED_LOCK``
452 1.1 joerg
453 1.1.1.2 joerg These are attributes on a function or method which asserts the calling thread
454 1.1.1.2 joerg already holds the given capability, for example by performing a run-time test
455 1.1.1.2 joerg and terminating if the capability is not held. Presence of this annotation
456 1.1.1.2 joerg causes the analysis to assume the capability is held after calls to the
457 1.1.1.2 joerg annotated function. See :ref:`mutexheader`, below, for example uses.
458 1.1 joerg
459 1.1 joerg
460 1.1 joerg GUARDED_VAR and PT_GUARDED_VAR
461 1.1 joerg ------------------------------
462 1.1 joerg
463 1.1 joerg Use of these attributes has been deprecated.
464 1.1 joerg
465 1.1 joerg
466 1.1 joerg Warning flags
467 1.1 joerg -------------
468 1.1 joerg
469 1.1 joerg * ``-Wthread-safety``: Umbrella flag which turns on the following three:
470 1.1 joerg
471 1.1 joerg + ``-Wthread-safety-attributes``: Sanity checks on attribute syntax.
472 1.1 joerg + ``-Wthread-safety-analysis``: The core analysis.
473 1.1 joerg + ``-Wthread-safety-precise``: Requires that mutex expressions match precisely.
474 1.1 joerg This warning can be disabled for code which has a lot of aliases.
475 1.1 joerg + ``-Wthread-safety-reference``: Checks when guarded members are passed by reference.
476 1.1 joerg
477 1.1 joerg
478 1.1 joerg :ref:`negative` are an experimental feature, which are enabled with:
479 1.1 joerg
480 1.1 joerg * ``-Wthread-safety-negative``: Negative capabilities. Off by default.
481 1.1 joerg
482 1.1 joerg When new features and checks are added to the analysis, they can often introduce
483 1.1 joerg additional warnings. Those warnings are initially released as *beta* warnings
484 1.1 joerg for a period of time, after which they are migrated into the standard analysis.
485 1.1 joerg
486 1.1 joerg * ``-Wthread-safety-beta``: New features. Off by default.
487 1.1 joerg
488 1.1 joerg
489 1.1 joerg .. _negative:
490 1.1 joerg
491 1.1 joerg Negative Capabilities
492 1.1 joerg =====================
493 1.1 joerg
494 1.1 joerg Thread Safety Analysis is designed to prevent both race conditions and
495 1.1 joerg deadlock. The GUARDED_BY and REQUIRES attributes prevent race conditions, by
496 1.1 joerg ensuring that a capability is held before reading or writing to guarded data,
497 1.1 joerg and the EXCLUDES attribute prevents deadlock, by making sure that a mutex is
498 1.1 joerg *not* held.
499 1.1 joerg
500 1.1 joerg However, EXCLUDES is an optional attribute, and does not provide the same
501 1.1 joerg safety guarantee as REQUIRES. In particular:
502 1.1 joerg
503 1.1 joerg * A function which acquires a capability does not have to exclude it.
504 1.1 joerg * A function which calls a function that excludes a capability does not
505 1.1 joerg have transitively exclude that capability.
506 1.1 joerg
507 1.1 joerg As a result, EXCLUDES can easily produce false negatives:
508 1.1 joerg
509 1.1 joerg .. code-block:: c++
510 1.1 joerg
511 1.1 joerg class Foo {
512 1.1 joerg Mutex mu;
513 1.1 joerg
514 1.1 joerg void foo() {
515 1.1 joerg mu.Lock();
516 1.1 joerg bar(); // No warning.
517 1.1 joerg baz(); // No warning.
518 1.1 joerg mu.Unlock();
519 1.1 joerg }
520 1.1 joerg
521 1.1 joerg void bar() { // No warning. (Should have EXCLUDES(mu)).
522 1.1 joerg mu.Lock();
523 1.1 joerg // ...
524 1.1 joerg mu.Unlock();
525 1.1 joerg }
526 1.1 joerg
527 1.1 joerg void baz() {
528 1.1 joerg bif(); // No warning. (Should have EXCLUDES(mu)).
529 1.1 joerg }
530 1.1 joerg
531 1.1 joerg void bif() EXCLUDES(mu);
532 1.1 joerg };
533 1.1 joerg
534 1.1 joerg
535 1.1 joerg Negative requirements are an alternative EXCLUDES that provide
536 1.1 joerg a stronger safety guarantee. A negative requirement uses the REQUIRES
537 1.1 joerg attribute, in conjunction with the ``!`` operator, to indicate that a capability
538 1.1 joerg should *not* be held.
539 1.1 joerg
540 1.1 joerg For example, using ``REQUIRES(!mu)`` instead of ``EXCLUDES(mu)`` will produce
541 1.1 joerg the appropriate warnings:
542 1.1 joerg
543 1.1 joerg .. code-block:: c++
544 1.1 joerg
545 1.1 joerg class FooNeg {
546 1.1 joerg Mutex mu;
547 1.1 joerg
548 1.1 joerg void foo() REQUIRES(!mu) { // foo() now requires !mu.
549 1.1 joerg mu.Lock();
550 1.1 joerg bar();
551 1.1 joerg baz();
552 1.1 joerg mu.Unlock();
553 1.1 joerg }
554 1.1 joerg
555 1.1 joerg void bar() {
556 1.1 joerg mu.Lock(); // WARNING! Missing REQUIRES(!mu).
557 1.1 joerg // ...
558 1.1 joerg mu.Unlock();
559 1.1 joerg }
560 1.1 joerg
561 1.1 joerg void baz() {
562 1.1 joerg bif(); // WARNING! Missing REQUIRES(!mu).
563 1.1 joerg }
564 1.1 joerg
565 1.1 joerg void bif() REQUIRES(!mu);
566 1.1 joerg };
567 1.1 joerg
568 1.1 joerg
569 1.1 joerg Negative requirements are an experimental feature which is off by default,
570 1.1 joerg because it will produce many warnings in existing code. It can be enabled
571 1.1 joerg by passing ``-Wthread-safety-negative``.
572 1.1 joerg
573 1.1 joerg
574 1.1 joerg .. _faq:
575 1.1 joerg
576 1.1 joerg Frequently Asked Questions
577 1.1 joerg ==========================
578 1.1 joerg
579 1.1 joerg (Q) Should I put attributes in the header file, or in the .cc/.cpp/.cxx file?
580 1.1 joerg
581 1.1 joerg (A) Attributes are part of the formal interface of a function, and should
582 1.1 joerg always go in the header, where they are visible to anything that includes
583 1.1 joerg the header. Attributes in the .cpp file are not visible outside of the
584 1.1 joerg immediate translation unit, which leads to false negatives and false positives.
585 1.1 joerg
586 1.1 joerg
587 1.1 joerg (Q) "*Mutex is not locked on every path through here?*" What does that mean?
588 1.1 joerg
589 1.1 joerg (A) See :ref:`conditional_locks`, below.
590 1.1 joerg
591 1.1 joerg
592 1.1 joerg .. _limitations:
593 1.1 joerg
594 1.1 joerg Known Limitations
595 1.1 joerg =================
596 1.1 joerg
597 1.1 joerg Lexical scope
598 1.1 joerg -------------
599 1.1 joerg
600 1.1 joerg Thread safety attributes contain ordinary C++ expressions, and thus follow
601 1.1 joerg ordinary C++ scoping rules. In particular, this means that mutexes and other
602 1.1 joerg capabilities must be declared before they can be used in an attribute.
603 1.1 joerg Use-before-declaration is okay within a single class, because attributes are
604 1.1 joerg parsed at the same time as method bodies. (C++ delays parsing of method bodies
605 1.1 joerg until the end of the class.) However, use-before-declaration is not allowed
606 1.1 joerg between classes, as illustrated below.
607 1.1 joerg
608 1.1 joerg .. code-block:: c++
609 1.1 joerg
610 1.1 joerg class Foo;
611 1.1 joerg
612 1.1 joerg class Bar {
613 1.1 joerg void bar(Foo* f) REQUIRES(f->mu); // Error: mu undeclared.
614 1.1 joerg };
615 1.1 joerg
616 1.1 joerg class Foo {
617 1.1 joerg Mutex mu;
618 1.1 joerg };
619 1.1 joerg
620 1.1 joerg
621 1.1 joerg Private Mutexes
622 1.1 joerg ---------------
623 1.1 joerg
624 1.1 joerg Good software engineering practice dictates that mutexes should be private
625 1.1 joerg members, because the locking mechanism used by a thread-safe class is part of
626 1.1 joerg its internal implementation. However, private mutexes can sometimes leak into
627 1.1 joerg the public interface of a class.
628 1.1 joerg Thread safety attributes follow normal C++ access restrictions, so if ``mu``
629 1.1 joerg is a private member of ``c``, then it is an error to write ``c.mu`` in an
630 1.1 joerg attribute.
631 1.1 joerg
632 1.1 joerg One workaround is to (ab)use the ``RETURN_CAPABILITY`` attribute to provide a
633 1.1 joerg public *name* for a private mutex, without actually exposing the underlying
634 1.1 joerg mutex. For example:
635 1.1 joerg
636 1.1 joerg .. code-block:: c++
637 1.1 joerg
638 1.1 joerg class MyClass {
639 1.1 joerg private:
640 1.1 joerg Mutex mu;
641 1.1 joerg
642 1.1 joerg public:
643 1.1 joerg // For thread safety analysis only. Does not actually return mu.
644 1.1 joerg Mutex* getMu() RETURN_CAPABILITY(mu) { return 0; }
645 1.1 joerg
646 1.1 joerg void doSomething() REQUIRES(mu);
647 1.1 joerg };
648 1.1 joerg
649 1.1 joerg void doSomethingTwice(MyClass& c) REQUIRES(c.getMu()) {
650 1.1 joerg // The analysis thinks that c.getMu() == c.mu
651 1.1 joerg c.doSomething();
652 1.1 joerg c.doSomething();
653 1.1 joerg }
654 1.1 joerg
655 1.1 joerg In the above example, ``doSomethingTwice()`` is an external routine that
656 1.1 joerg requires ``c.mu`` to be locked, which cannot be declared directly because ``mu``
657 1.1 joerg is private. This pattern is discouraged because it
658 1.1 joerg violates encapsulation, but it is sometimes necessary, especially when adding
659 1.1 joerg annotations to an existing code base. The workaround is to define ``getMu()``
660 1.1 joerg as a fake getter method, which is provided only for the benefit of thread
661 1.1 joerg safety analysis.
662 1.1 joerg
663 1.1 joerg
664 1.1 joerg .. _conditional_locks:
665 1.1 joerg
666 1.1 joerg No conditionally held locks.
667 1.1 joerg ----------------------------
668 1.1 joerg
669 1.1 joerg The analysis must be able to determine whether a lock is held, or not held, at
670 1.1 joerg every program point. Thus, sections of code where a lock *might be held* will
671 1.1 joerg generate spurious warnings (false positives). For example:
672 1.1 joerg
673 1.1 joerg .. code-block:: c++
674 1.1 joerg
675 1.1 joerg void foo() {
676 1.1 joerg bool b = needsToLock();
677 1.1 joerg if (b) mu.Lock();
678 1.1 joerg ... // Warning! Mutex 'mu' is not held on every path through here.
679 1.1 joerg if (b) mu.Unlock();
680 1.1 joerg }
681 1.1 joerg
682 1.1 joerg
683 1.1 joerg No checking inside constructors and destructors.
684 1.1 joerg ------------------------------------------------
685 1.1 joerg
686 1.1 joerg The analysis currently does not do any checking inside constructors or
687 1.1 joerg destructors. In other words, every constructor and destructor is treated as
688 1.1 joerg if it was annotated with ``NO_THREAD_SAFETY_ANALYSIS``.
689 1.1 joerg The reason for this is that during initialization, only one thread typically
690 1.1 joerg has access to the object which is being initialized, and it is thus safe (and
691 1.1 joerg common practice) to initialize guarded members without acquiring any locks.
692 1.1 joerg The same is true of destructors.
693 1.1 joerg
694 1.1 joerg Ideally, the analysis would allow initialization of guarded members inside the
695 1.1 joerg object being initialized or destroyed, while still enforcing the usual access
696 1.1 joerg restrictions on everything else. However, this is difficult to enforce in
697 1.1 joerg practice, because in complex pointer-based data structures, it is hard to
698 1.1 joerg determine what data is owned by the enclosing object.
699 1.1 joerg
700 1.1 joerg No inlining.
701 1.1 joerg ------------
702 1.1 joerg
703 1.1 joerg Thread safety analysis is strictly intra-procedural, just like ordinary type
704 1.1 joerg checking. It relies only on the declared attributes of a function, and will
705 1.1 joerg not attempt to inline any method calls. As a result, code such as the
706 1.1 joerg following will not work:
707 1.1 joerg
708 1.1 joerg .. code-block:: c++
709 1.1 joerg
710 1.1 joerg template<class T>
711 1.1 joerg class AutoCleanup {
712 1.1 joerg T* object;
713 1.1 joerg void (T::*mp)();
714 1.1 joerg
715 1.1 joerg public:
716 1.1 joerg AutoCleanup(T* obj, void (T::*imp)()) : object(obj), mp(imp) { }
717 1.1 joerg ~AutoCleanup() { (object->*mp)(); }
718 1.1 joerg };
719 1.1 joerg
720 1.1 joerg Mutex mu;
721 1.1 joerg void foo() {
722 1.1 joerg mu.Lock();
723 1.1 joerg AutoCleanup<Mutex>(&mu, &Mutex::Unlock);
724 1.1 joerg // ...
725 1.1 joerg } // Warning, mu is not unlocked.
726 1.1 joerg
727 1.1 joerg In this case, the destructor of ``Autocleanup`` calls ``mu.Unlock()``, so
728 1.1 joerg the warning is bogus. However,
729 1.1 joerg thread safety analysis cannot see the unlock, because it does not attempt to
730 1.1 joerg inline the destructor. Moreover, there is no way to annotate the destructor,
731 1.1 joerg because the destructor is calling a function that is not statically known.
732 1.1 joerg This pattern is simply not supported.
733 1.1 joerg
734 1.1 joerg
735 1.1 joerg No alias analysis.
736 1.1 joerg ------------------
737 1.1 joerg
738 1.1 joerg The analysis currently does not track pointer aliases. Thus, there can be
739 1.1 joerg false positives if two pointers both point to the same mutex.
740 1.1 joerg
741 1.1 joerg
742 1.1 joerg .. code-block:: c++
743 1.1 joerg
744 1.1 joerg class MutexUnlocker {
745 1.1 joerg Mutex* mu;
746 1.1 joerg
747 1.1 joerg public:
748 1.1 joerg MutexUnlocker(Mutex* m) RELEASE(m) : mu(m) { mu->Unlock(); }
749 1.1 joerg ~MutexUnlocker() ACQUIRE(mu) { mu->Lock(); }
750 1.1 joerg };
751 1.1 joerg
752 1.1 joerg Mutex mutex;
753 1.1 joerg void test() REQUIRES(mutex) {
754 1.1 joerg {
755 1.1 joerg MutexUnlocker munl(&mutex); // unlocks mutex
756 1.1 joerg doSomeIO();
757 1.1 joerg } // Warning: locks munl.mu
758 1.1 joerg }
759 1.1 joerg
760 1.1 joerg The MutexUnlocker class is intended to be the dual of the MutexLocker class,
761 1.1 joerg defined in :ref:`mutexheader`. However, it doesn't work because the analysis
762 1.1 joerg doesn't know that munl.mu == mutex. The SCOPED_CAPABILITY attribute handles
763 1.1 joerg aliasing for MutexLocker, but does so only for that particular pattern.
764 1.1 joerg
765 1.1 joerg
766 1.1 joerg ACQUIRED_BEFORE(...) and ACQUIRED_AFTER(...) are currently unimplemented.
767 1.1 joerg -------------------------------------------------------------------------
768 1.1 joerg
769 1.1 joerg To be fixed in a future update.
770 1.1 joerg
771 1.1 joerg
772 1.1 joerg .. _mutexheader:
773 1.1 joerg
774 1.1 joerg mutex.h
775 1.1 joerg =======
776 1.1 joerg
777 1.1 joerg Thread safety analysis can be used with any threading library, but it does
778 1.1 joerg require that the threading API be wrapped in classes and methods which have the
779 1.1 joerg appropriate annotations. The following code provides ``mutex.h`` as an example;
780 1.1 joerg these methods should be filled in to call the appropriate underlying
781 1.1 joerg implementation.
782 1.1 joerg
783 1.1 joerg
784 1.1 joerg .. code-block:: c++
785 1.1 joerg
786 1.1 joerg
787 1.1 joerg #ifndef THREAD_SAFETY_ANALYSIS_MUTEX_H
788 1.1 joerg #define THREAD_SAFETY_ANALYSIS_MUTEX_H
789 1.1 joerg
790 1.1 joerg // Enable thread safety attributes only with clang.
791 1.1 joerg // The attributes can be safely erased when compiling with other compilers.
792 1.1 joerg #if defined(__clang__) && (!defined(SWIG))
793 1.1 joerg #define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
794 1.1 joerg #else
795 1.1 joerg #define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op
796 1.1 joerg #endif
797 1.1 joerg
798 1.1 joerg #define CAPABILITY(x) \
799 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(capability(x))
800 1.1 joerg
801 1.1 joerg #define SCOPED_CAPABILITY \
802 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
803 1.1 joerg
804 1.1 joerg #define GUARDED_BY(x) \
805 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
806 1.1 joerg
807 1.1 joerg #define PT_GUARDED_BY(x) \
808 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))
809 1.1 joerg
810 1.1 joerg #define ACQUIRED_BEFORE(...) \
811 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__))
812 1.1 joerg
813 1.1 joerg #define ACQUIRED_AFTER(...) \
814 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__))
815 1.1 joerg
816 1.1 joerg #define REQUIRES(...) \
817 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__))
818 1.1 joerg
819 1.1 joerg #define REQUIRES_SHARED(...) \
820 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__))
821 1.1 joerg
822 1.1 joerg #define ACQUIRE(...) \
823 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__))
824 1.1 joerg
825 1.1 joerg #define ACQUIRE_SHARED(...) \
826 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__))
827 1.1 joerg
828 1.1 joerg #define RELEASE(...) \
829 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__))
830 1.1 joerg
831 1.1 joerg #define RELEASE_SHARED(...) \
832 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__))
833 1.1 joerg
834 1.1.1.2 joerg #define RELEASE_GENERIC(...) \
835 1.1.1.2 joerg THREAD_ANNOTATION_ATTRIBUTE__(release_generic_capability(__VA_ARGS__))
836 1.1.1.2 joerg
837 1.1 joerg #define TRY_ACQUIRE(...) \
838 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__))
839 1.1 joerg
840 1.1 joerg #define TRY_ACQUIRE_SHARED(...) \
841 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__))
842 1.1 joerg
843 1.1 joerg #define EXCLUDES(...) \
844 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
845 1.1 joerg
846 1.1 joerg #define ASSERT_CAPABILITY(x) \
847 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x))
848 1.1 joerg
849 1.1 joerg #define ASSERT_SHARED_CAPABILITY(x) \
850 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x))
851 1.1 joerg
852 1.1 joerg #define RETURN_CAPABILITY(x) \
853 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
854 1.1 joerg
855 1.1 joerg #define NO_THREAD_SAFETY_ANALYSIS \
856 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
857 1.1 joerg
858 1.1 joerg
859 1.1 joerg // Defines an annotated interface for mutexes.
860 1.1 joerg // These methods can be implemented to use any internal mutex implementation.
861 1.1 joerg class CAPABILITY("mutex") Mutex {
862 1.1 joerg public:
863 1.1 joerg // Acquire/lock this mutex exclusively. Only one thread can have exclusive
864 1.1 joerg // access at any one time. Write operations to guarded data require an
865 1.1 joerg // exclusive lock.
866 1.1 joerg void Lock() ACQUIRE();
867 1.1 joerg
868 1.1 joerg // Acquire/lock this mutex for read operations, which require only a shared
869 1.1 joerg // lock. This assumes a multiple-reader, single writer semantics. Multiple
870 1.1 joerg // threads may acquire the mutex simultaneously as readers, but a writer
871 1.1 joerg // must wait for all of them to release the mutex before it can acquire it
872 1.1 joerg // exclusively.
873 1.1 joerg void ReaderLock() ACQUIRE_SHARED();
874 1.1 joerg
875 1.1 joerg // Release/unlock an exclusive mutex.
876 1.1 joerg void Unlock() RELEASE();
877 1.1 joerg
878 1.1 joerg // Release/unlock a shared mutex.
879 1.1 joerg void ReaderUnlock() RELEASE_SHARED();
880 1.1 joerg
881 1.1.1.2 joerg // Generic unlock, can unlock exclusive and shared mutexes.
882 1.1.1.2 joerg void GenericUnlock() RELEASE_GENERIC();
883 1.1.1.2 joerg
884 1.1 joerg // Try to acquire the mutex. Returns true on success, and false on failure.
885 1.1 joerg bool TryLock() TRY_ACQUIRE(true);
886 1.1 joerg
887 1.1 joerg // Try to acquire the mutex for read operations.
888 1.1 joerg bool ReaderTryLock() TRY_ACQUIRE_SHARED(true);
889 1.1 joerg
890 1.1 joerg // Assert that this mutex is currently held by the calling thread.
891 1.1 joerg void AssertHeld() ASSERT_CAPABILITY(this);
892 1.1 joerg
893 1.1 joerg // Assert that is mutex is currently held for read operations.
894 1.1 joerg void AssertReaderHeld() ASSERT_SHARED_CAPABILITY(this);
895 1.1 joerg
896 1.1 joerg // For negative capabilities.
897 1.1 joerg const Mutex& operator!() const { return *this; }
898 1.1 joerg };
899 1.1 joerg
900 1.1.1.2 joerg // Tag types for selecting a constructor.
901 1.1.1.2 joerg struct adopt_lock_t {} inline constexpr adopt_lock = {};
902 1.1.1.2 joerg struct defer_lock_t {} inline constexpr defer_lock = {};
903 1.1.1.2 joerg struct shared_lock_t {} inline constexpr shared_lock = {};
904 1.1 joerg
905 1.1 joerg // MutexLocker is an RAII class that acquires a mutex in its constructor, and
906 1.1 joerg // releases it in its destructor.
907 1.1 joerg class SCOPED_CAPABILITY MutexLocker {
908 1.1 joerg private:
909 1.1 joerg Mutex* mut;
910 1.1.1.2 joerg bool locked;
911 1.1 joerg
912 1.1 joerg public:
913 1.1.1.2 joerg // Acquire mu, implicitly acquire *this and associate it with mu.
914 1.1.1.2 joerg MutexLocker(Mutex *mu) ACQUIRE(mu) : mut(mu), locked(true) {
915 1.1 joerg mu->Lock();
916 1.1 joerg }
917 1.1.1.2 joerg
918 1.1.1.2 joerg // Assume mu is held, implicitly acquire *this and associate it with mu.
919 1.1.1.2 joerg MutexLocker(Mutex *mu, adopt_lock_t) REQUIRES(mu) : mut(mu), locked(true) {}
920 1.1.1.2 joerg
921 1.1.1.2 joerg // Acquire mu in shared mode, implicitly acquire *this and associate it with mu.
922 1.1.1.2 joerg MutexLocker(Mutex *mu, shared_lock_t) ACQUIRE_SHARED(mu) : mut(mu), locked(true) {
923 1.1.1.2 joerg mu->ReaderLock();
924 1.1.1.2 joerg }
925 1.1.1.2 joerg
926 1.1.1.2 joerg // Assume mu is held in shared mode, implicitly acquire *this and associate it with mu.
927 1.1.1.2 joerg MutexLocker(Mutex *mu, adopt_lock_t, shared_lock_t) REQUIRES_SHARED(mu)
928 1.1.1.2 joerg : mut(mu), locked(true) {}
929 1.1.1.2 joerg
930 1.1.1.2 joerg // Assume mu is not held, implicitly acquire *this and associate it with mu.
931 1.1.1.2 joerg MutexLocker(Mutex *mu, defer_lock_t) EXCLUDES(mu) : mut(mu), locked(false) {}
932 1.1.1.2 joerg
933 1.1.1.2 joerg // Release *this and all associated mutexes, if they are still held.
934 1.1.1.2 joerg // There is no warning if the scope was already unlocked before.
935 1.1 joerg ~MutexLocker() RELEASE() {
936 1.1.1.2 joerg if (locked)
937 1.1.1.2 joerg mut->GenericUnlock();
938 1.1.1.2 joerg }
939 1.1.1.2 joerg
940 1.1.1.2 joerg // Acquire all associated mutexes exclusively.
941 1.1.1.2 joerg void Lock() ACQUIRE() {
942 1.1.1.2 joerg mut->Lock();
943 1.1.1.2 joerg locked = true;
944 1.1.1.2 joerg }
945 1.1.1.2 joerg
946 1.1.1.2 joerg // Try to acquire all associated mutexes exclusively.
947 1.1.1.2 joerg bool TryLock() TRY_ACQUIRE(true) {
948 1.1.1.2 joerg return locked = mut->TryLock();
949 1.1.1.2 joerg }
950 1.1.1.2 joerg
951 1.1.1.2 joerg // Acquire all associated mutexes in shared mode.
952 1.1.1.2 joerg void ReaderLock() ACQUIRE_SHARED() {
953 1.1.1.2 joerg mut->ReaderLock();
954 1.1.1.2 joerg locked = true;
955 1.1.1.2 joerg }
956 1.1.1.2 joerg
957 1.1.1.2 joerg // Try to acquire all associated mutexes in shared mode.
958 1.1.1.2 joerg bool ReaderTryLock() TRY_ACQUIRE_SHARED(true) {
959 1.1.1.2 joerg return locked = mut->ReaderTryLock();
960 1.1.1.2 joerg }
961 1.1.1.2 joerg
962 1.1.1.2 joerg // Release all associated mutexes. Warn on double unlock.
963 1.1.1.2 joerg void Unlock() RELEASE() {
964 1.1 joerg mut->Unlock();
965 1.1.1.2 joerg locked = false;
966 1.1.1.2 joerg }
967 1.1.1.2 joerg
968 1.1.1.2 joerg // Release all associated mutexes. Warn on double unlock.
969 1.1.1.2 joerg void ReaderUnlock() RELEASE() {
970 1.1.1.2 joerg mut->ReaderUnlock();
971 1.1.1.2 joerg locked = false;
972 1.1 joerg }
973 1.1 joerg };
974 1.1 joerg
975 1.1 joerg
976 1.1 joerg #ifdef USE_LOCK_STYLE_THREAD_SAFETY_ATTRIBUTES
977 1.1 joerg // The original version of thread safety analysis the following attribute
978 1.1 joerg // definitions. These use a lock-based terminology. They are still in use
979 1.1 joerg // by existing thread safety code, and will continue to be supported.
980 1.1 joerg
981 1.1 joerg // Deprecated.
982 1.1 joerg #define PT_GUARDED_VAR \
983 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_var)
984 1.1 joerg
985 1.1 joerg // Deprecated.
986 1.1 joerg #define GUARDED_VAR \
987 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(guarded_var)
988 1.1 joerg
989 1.1 joerg // Replaced by REQUIRES
990 1.1 joerg #define EXCLUSIVE_LOCKS_REQUIRED(...) \
991 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__))
992 1.1 joerg
993 1.1 joerg // Replaced by REQUIRES_SHARED
994 1.1 joerg #define SHARED_LOCKS_REQUIRED(...) \
995 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(__VA_ARGS__))
996 1.1 joerg
997 1.1 joerg // Replaced by CAPABILITY
998 1.1 joerg #define LOCKABLE \
999 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(lockable)
1000 1.1 joerg
1001 1.1 joerg // Replaced by SCOPED_CAPABILITY
1002 1.1 joerg #define SCOPED_LOCKABLE \
1003 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
1004 1.1 joerg
1005 1.1 joerg // Replaced by ACQUIRE
1006 1.1 joerg #define EXCLUSIVE_LOCK_FUNCTION(...) \
1007 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(__VA_ARGS__))
1008 1.1 joerg
1009 1.1 joerg // Replaced by ACQUIRE_SHARED
1010 1.1 joerg #define SHARED_LOCK_FUNCTION(...) \
1011 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(shared_lock_function(__VA_ARGS__))
1012 1.1 joerg
1013 1.1 joerg // Replaced by RELEASE and RELEASE_SHARED
1014 1.1 joerg #define UNLOCK_FUNCTION(...) \
1015 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(__VA_ARGS__))
1016 1.1 joerg
1017 1.1 joerg // Replaced by TRY_ACQUIRE
1018 1.1 joerg #define EXCLUSIVE_TRYLOCK_FUNCTION(...) \
1019 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock_function(__VA_ARGS__))
1020 1.1 joerg
1021 1.1 joerg // Replaced by TRY_ACQUIRE_SHARED
1022 1.1 joerg #define SHARED_TRYLOCK_FUNCTION(...) \
1023 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock_function(__VA_ARGS__))
1024 1.1 joerg
1025 1.1 joerg // Replaced by ASSERT_CAPABILITY
1026 1.1 joerg #define ASSERT_EXCLUSIVE_LOCK(...) \
1027 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(assert_exclusive_lock(__VA_ARGS__))
1028 1.1 joerg
1029 1.1 joerg // Replaced by ASSERT_SHARED_CAPABILITY
1030 1.1 joerg #define ASSERT_SHARED_LOCK(...) \
1031 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_lock(__VA_ARGS__))
1032 1.1 joerg
1033 1.1 joerg // Replaced by EXCLUDE_CAPABILITY.
1034 1.1 joerg #define LOCKS_EXCLUDED(...) \
1035 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
1036 1.1 joerg
1037 1.1 joerg // Replaced by RETURN_CAPABILITY
1038 1.1 joerg #define LOCK_RETURNED(x) \
1039 1.1 joerg THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
1040 1.1 joerg
1041 1.1 joerg #endif // USE_LOCK_STYLE_THREAD_SAFETY_ATTRIBUTES
1042 1.1 joerg
1043 1.1 joerg #endif // THREAD_SAFETY_ANALYSIS_MUTEX_H
1044 1.1 joerg
1045