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