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