Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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 |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 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. |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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 |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 24 | routines. |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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); |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 37 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 38 | void depositImpl(int amount) { |
| 39 | balance += amount; // WARNING! Cannot write balance without locking mu. |
| 40 | } |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 41 | |
| 42 | void withdrawImpl(int amount) REQUIRES(mu) { |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 43 | balance -= amount; // OK. Caller must have locked mu. |
| 44 | } |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 45 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 46 | public: |
| 47 | void withdraw(int amount) { |
| 48 | mu.Lock(); |
| 49 | withdrawImpl(amount); // OK. We've locked mu. |
| 50 | } // WARNING! Failed to unlock mu. |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 51 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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 |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 63 | operations are atomic. Similarly, ``REQUIRES`` declares that |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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 | |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 68 | The ``depositImpl()`` method does not have ``REQUIRES``, so the |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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 |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 73 | that these are two separate mutexes, in two different objects. |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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 |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 79 | as such (using ``ACQUIRE``/``RELEASE``). |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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, |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 93 | unlocking, and so on. |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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 |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 109 | to acquire the capability to access data that is protected by ``mu``. Similarly, |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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 |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 116 | require exclusive access, while read operations require only shared access. |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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 |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 124 | exact mechanism used to acquire and release capabilities; it assumes that the |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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 | |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 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 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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 |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 162 | it points to* is protected by the given capability. |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 163 | |
| 164 | .. code-block:: c++ |
| 165 | |
| 166 | Mutex mu; |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 167 | int *p1 GUARDED_BY(mu); |
| 168 | int *p2 PT_GUARDED_BY(mu); |
| 169 | unique_ptr<int> p3 PT_GUARDED_BY(mu); |
| 170 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 171 | void test() { |
| 172 | p1 = 0; // Warning! |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 173 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 174 | *p2 = 42; // Warning! |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 175 | p2 = new int; // OK. |
| 176 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 177 | *p3 = 42; // Warning! |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 178 | p3.reset(new int); // OK. |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 179 | } |
| 180 | |
| 181 | |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 182 | REQUIRES(...), REQUIRES_SHARED(...) |
| 183 | ----------------------------------- |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 184 | |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 185 | *Previously*: ``EXCLUSIVE_LOCKS_REQUIRED``, ``SHARED_LOCKS_REQUIRED`` |
| 186 | |
| 187 | ``REQUIRES`` is an attribute on functions or methods, which |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 188 | declares that the calling thread must have exclusive access to the given |
| 189 | capabilities. More than one capability may be specified. The capabilities |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 190 | must be held on entry to the function, *and must still be held on exit*. |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 191 | |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 192 | ``REQUIRES_SHARED`` is similar, but requires only shared access. |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 193 | |
| 194 | .. code-block:: c++ |
| 195 | |
| 196 | Mutex mu1, mu2; |
| 197 | int a GUARDED_BY(mu1); |
| 198 | int b GUARDED_BY(mu2); |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 199 | |
| 200 | void foo() REQUIRES(mu1, mu2) { |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 201 | a = 0; |
| 202 | b = 0; |
| 203 | } |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 204 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 205 | void test() { |
| 206 | mu1.Lock(); |
| 207 | foo(); // Warning! Requires mu2. |
| 208 | mu1.Unlock(); |
| 209 | } |
| 210 | |
| 211 | |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 212 | ACQUIRE(...), ACQUIRE_SHARED(...), RELEASE(...), RELEASE_SHARED(...) |
| 213 | -------------------------------------------------------------------- |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 214 | |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 215 | *Previously*: ``EXCLUSIVE_LOCK_FUNCTION``, ``SHARED_LOCK_FUNCTION``, |
| 216 | ``UNLOCK_FUNCTION`` |
| 217 | |
| 218 | ``ACQUIRE`` is an attribute on functions or methods, which |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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 |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 221 | capability on exit. ``ACQUIRE_SHARED`` is similar. |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 222 | |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 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. |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 227 | |
| 228 | .. code-block:: c++ |
| 229 | |
| 230 | Mutex mu; |
| 231 | MyClass myObject GUARDED_BY(mu); |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 232 | |
| 233 | void lockAndInit() ACQUIRE(mu) { |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 234 | mu.Lock(); |
| 235 | myObject.init(); |
| 236 | } |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 237 | |
| 238 | void cleanupAndUnlock() RELEASE(mu) { |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 239 | myObject.cleanup(); |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 240 | } // Warning! Need to unlock mu. |
| 241 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 242 | void test() { |
| 243 | lockAndInit(); |
| 244 | myObject.doSomething(); |
| 245 | cleanupAndUnlock(); |
| 246 | myObject.doSomething(); // Warning, mu is not locked. |
| 247 | } |
| 248 | |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 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: |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 253 | |
| 254 | .. code-block:: c++ |
| 255 | |
| 256 | template <class T> |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 257 | class CAPABILITY("mutex") Container { |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 258 | private: |
| 259 | Mutex mu; |
| 260 | T* data; |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 261 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 262 | public: |
| 263 | // Hide mu from public interface. |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 264 | void Lock() ACQUIRE() { mu.Lock(); } |
| 265 | void Unlock() RELEASE() { mu.Unlock(); } |
| 266 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 267 | T& getElem(int i) { return data[i]; } |
| 268 | }; |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 269 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 270 | void test() { |
| 271 | Container<int> c; |
| 272 | c.Lock(); |
| 273 | int i = c.getElem(0); |
| 274 | c.Unlock(); |
| 275 | } |
| 276 | |
| 277 | |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 278 | EXCLUDES(...) |
| 279 | ------------- |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 280 | |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 281 | *Previously*: ``LOCKS_EXCLUDED`` |
| 282 | |
| 283 | ``EXCLUDES`` is an attribute on functions or methods, which declares that |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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 |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 286 | deadlock can occur if the function acquires the mutex a second time. |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 287 | |
| 288 | .. code-block:: c++ |
| 289 | |
| 290 | Mutex mu; |
| 291 | int a GUARDED_BY(mu); |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 292 | |
| 293 | void clear() EXCLUDES(mu) { |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 294 | mu.Lock(); |
| 295 | a = 0; |
| 296 | mu.Unlock(); |
| 297 | } |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 298 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 299 | void reset() { |
| 300 | mu.Lock(); |
| 301 | clear(); // Warning! Caller cannot hold 'mu'. |
| 302 | mu.Unlock(); |
| 303 | } |
| 304 | |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 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`. |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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); |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 324 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 325 | void unsafeIncrement() NO_THREAD_SAFETY_ANALYSIS { a++; } |
| 326 | }; |
| 327 | |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 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). |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 332 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 333 | |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 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 |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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); |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 349 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 350 | public: |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 351 | Mutex* getMu() RETURN_CAPABILITY(mu) { return μ } |
| 352 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 353 | // analysis knows that getMu() == mu |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 354 | void clear() REQUIRES(getMu()) { a = 0; } |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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); |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 370 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 371 | // Alternative declaration |
| 372 | // Mutex m2; |
| 373 | // Mutex m1 ACQUIRED_BEFORE(m2); |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 374 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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 | |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 383 | CAPABILITY(<string>) |
| 384 | -------------------- |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 385 | |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 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`. |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 392 | |
| 393 | |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 394 | SCOPED_CAPABILITY |
| 395 | ----------------- |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 396 | |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 397 | *Previously*: ``SCOPED_LOCKABLE`` |
| 398 | |
| 399 | ``SCOPED_CAPABILITY`` is an attribute on classes that implement RAII-style |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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 | |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 406 | TRY_ACQUIRE(<bool>, ...), TRY_ACQUIRE_SHARED(<bool>, ...) |
| 407 | --------------------------------------------------------- |
| 408 | |
| 409 | *Previously:* ``EXCLUSIVE_TRYLOCK_FUNCTION``, ``SHARED_TRYLOCK_FUNCTION`` |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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 |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 415 | as ``ACQUIRE``. See :ref:`mutexheader`, below, for example uses. |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 416 | |
| 417 | |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 418 | ASSERT_CAPABILITY(...) and ASSERT_SHARED_CAPABILITY(...) |
| 419 | -------------------------------------------------------- |
| 420 | |
| 421 | *Previously:* ``ASSERT_EXCLUSIVE_LOCK``, ``ASSERT_SHARED_LOCK`` |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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. |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 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. |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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 |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 453 | for a period of time, after which they are migrated into the standard analysis. |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 454 | |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 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``. |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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 | |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 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. |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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 | |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 563 | Known Limitations |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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 |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 575 | between classes, as illustrated below. |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 576 | |
| 577 | .. code-block:: c++ |
| 578 | |
| 579 | class Foo; |
| 580 | |
| 581 | class Bar { |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 582 | void bar(Foo* f) REQUIRES(f->mu); // Error: mu undeclared. |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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 | |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 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: |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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. |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 613 | Mutex* getMu() RETURN_CAPABILITY(mu) { return 0; } |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 614 | |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 615 | void doSomething() REQUIRES(mu); |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 616 | }; |
| 617 | |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 618 | void doSomethingTwice(MyClass& c) REQUIRES(c.getMu()) { |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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(); |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 647 | ... // Warning! Mutex 'mu' is not held on every path through here. |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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 |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 657 | if it was annotated with ``NO_THREAD_SAFETY_ANALYSIS``. |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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 |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 667 | determine what data is owned by the enclosing object. |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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 |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 674 | not attempt to inline any method calls. As a result, code such as the |
| 675 | following will not work: |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 676 | |
| 677 | .. code-block:: c++ |
| 678 | |
| 679 | template<class T> |
| 680 | class AutoCleanup { |
| 681 | T* object; |
| 682 | void (T::*mp)(); |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 683 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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(); |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 692 | AutoCleanup<Mutex>(&mu, &Mutex::Unlock); |
| 693 | // ... |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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. |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 701 | This pattern is simply not supported. |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 702 | |
| 703 | |
| 704 | No alias analysis. |
| 705 | ------------------ |
| 706 | |
| 707 | The analysis currently does not track pointer aliases. Thus, there can be |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 708 | false positives if two pointers both point to the same mutex. |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 709 | |
| 710 | |
| 711 | .. code-block:: c++ |
| 712 | |
| 713 | class MutexUnlocker { |
| 714 | Mutex* mu; |
| 715 | |
| 716 | public: |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 717 | MutexUnlocker(Mutex* m) RELEASE(m) : mu(m) { mu->Unlock(); } |
| 718 | ~MutexUnlocker() ACQUIRE(mu) { mu->Lock(); } |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 719 | }; |
| 720 | |
| 721 | Mutex mutex; |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 722 | void test() REQUIRES(mutex) { |
| 723 | { |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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 |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 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. |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 733 | |
| 734 | |
| 735 | ACQUIRED_BEFORE(...) and ACQUIRED_AFTER(...) are currently unimplemented. |
| 736 | ------------------------------------------------------------------------- |
| 737 | |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 738 | To be fixed in a future update. |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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 |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 750 | implementation. |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 751 | |
| 752 | |
| 753 | .. code-block:: c++ |
| 754 | |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 755 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 756 | #ifndef THREAD_SAFETY_ANALYSIS_MUTEX_H |
| 757 | #define THREAD_SAFETY_ANALYSIS_MUTEX_H |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 758 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 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 |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 766 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 767 | #define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 768 | |
| 769 | #define CAPABILITY(x) \ |
| 770 | THREAD_ANNOTATION_ATTRIBUTE__(capability(x)) |
| 771 | |
| 772 | #define SCOPED_CAPABILITY \ |
| 773 | THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable) |
| 774 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 775 | #define GUARDED_BY(x) \ |
| 776 | THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 777 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 778 | #define PT_GUARDED_BY(x) \ |
| 779 | THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x)) |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 780 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 781 | #define ACQUIRED_BEFORE(...) \ |
| 782 | THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__)) |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 783 | |
| 784 | #define ACQUIRED_AFTER(...) \ |
| 785 | THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__)) |
| 786 | |
| 787 | #define REQUIRES(...) \ |
| 788 | THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__)) |
| 789 | |
| 790 | #define REQUIRES_SHARED(...) \ |
| 791 | THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__)) |
| 792 | |
| 793 | #define ACQUIRE(...) \ |
| 794 | THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__)) |
| 795 | |
| 796 | #define ACQUIRE_SHARED(...) \ |
| 797 | THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__)) |
| 798 | |
| 799 | #define RELEASE(...) \ |
| 800 | THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__)) |
| 801 | |
| 802 | #define RELEASE_SHARED(...) \ |
| 803 | THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__)) |
| 804 | |
| 805 | #define TRY_ACQUIRE(...) \ |
| 806 | THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__)) |
| 807 | |
| 808 | #define TRY_ACQUIRE_SHARED(...) \ |
| 809 | THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__)) |
| 810 | |
| 811 | #define EXCLUDES(...) \ |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 812 | THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__)) |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 813 | |
| 814 | #define ASSERT_CAPABILITY(x) \ |
| 815 | THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x)) |
| 816 | |
| 817 | #define ASSERT_SHARED_CAPABILITY(x) \ |
| 818 | THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x)) |
| 819 | |
| 820 | #define RETURN_CAPABILITY(x) \ |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 821 | THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 822 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 823 | #define NO_THREAD_SAFETY_ANALYSIS \ |
| 824 | THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 825 | |
| 826 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 827 | // Defines an annotated interface for mutexes. |
| 828 | // These methods can be implemented to use any internal mutex implementation. |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 829 | class CAPABILITY("mutex") Mutex { |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 830 | public: |
| 831 | // Acquire/lock this mutex exclusively. Only one thread can have exclusive |
| 832 | // access at any one time. Write operations to guarded data require an |
| 833 | // exclusive lock. |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 834 | void Lock() ACQUIRE(); |
| 835 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 836 | // Acquire/lock this mutex for read operations, which require only a shared |
| 837 | // lock. This assumes a multiple-reader, single writer semantics. Multiple |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 838 | // threads may acquire the mutex simultaneously as readers, but a writer |
| 839 | // must wait for all of them to release the mutex before it can acquire it |
| 840 | // exclusively. |
| 841 | void ReaderLock() ACQUIRE_SHARED(); |
| 842 | |
| 843 | // Release/unlock an exclusive mutex. |
| 844 | void Unlock() RELEASE(); |
| 845 | |
| 846 | // Release/unlock a shared mutex. |
| 847 | void ReaderUnlock() RELEASE_SHARED(); |
| 848 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 849 | // Try to acquire the mutex. Returns true on success, and false on failure. |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 850 | bool TryLock() TRY_ACQUIRE(true); |
| 851 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 852 | // Try to acquire the mutex for read operations. |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 853 | bool ReaderTryLock() TRY_ACQUIRE_SHARED(true); |
| 854 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 855 | // Assert that this mutex is currently held by the calling thread. |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 856 | void AssertHeld() ASSERT_CAPABILITY(this); |
| 857 | |
| 858 | // Assert that is mutex is currently held for read operations. |
| 859 | void AssertReaderHeld() ASSERT_SHARED_CAPABILITY(this); |
Pirama Arumuga Nainar | b6d6993 | 2015-07-01 12:25:36 -0700 | [diff] [blame] | 860 | |
| 861 | // For negative capabilities. |
| 862 | const Mutex& operator!() const { return *this; } |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 863 | }; |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 864 | |
| 865 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 866 | // MutexLocker is an RAII class that acquires a mutex in its constructor, and |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 867 | // releases it in its destructor. |
| 868 | class SCOPED_CAPABILITY MutexLocker { |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 869 | private: |
| 870 | Mutex* mut; |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 871 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 872 | public: |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 873 | MutexLocker(Mutex *mu) ACQUIRE(mu) : mut(mu) { |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 874 | mu->Lock(); |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 875 | } |
| 876 | ~MutexLocker() RELEASE() { |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 877 | mut->Unlock(); |
| 878 | } |
| 879 | }; |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 880 | |
| 881 | |
| 882 | #ifdef USE_LOCK_STYLE_THREAD_SAFETY_ATTRIBUTES |
| 883 | // The original version of thread safety analysis the following attribute |
| 884 | // definitions. These use a lock-based terminology. They are still in use |
| 885 | // by existing thread safety code, and will continue to be supported. |
| 886 | |
| 887 | // Deprecated. |
| 888 | #define PT_GUARDED_VAR \ |
| 889 | THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded) |
| 890 | |
| 891 | // Deprecated. |
| 892 | #define GUARDED_VAR \ |
| 893 | THREAD_ANNOTATION_ATTRIBUTE__(guarded) |
| 894 | |
| 895 | // Replaced by REQUIRES |
| 896 | #define EXCLUSIVE_LOCKS_REQUIRED(...) \ |
| 897 | THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__)) |
| 898 | |
| 899 | // Replaced by REQUIRES_SHARED |
| 900 | #define SHARED_LOCKS_REQUIRED(...) \ |
| 901 | THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(__VA_ARGS__)) |
| 902 | |
| 903 | // Replaced by CAPABILITY |
| 904 | #define LOCKABLE \ |
| 905 | THREAD_ANNOTATION_ATTRIBUTE__(lockable) |
| 906 | |
| 907 | // Replaced by SCOPED_CAPABILITY |
| 908 | #define SCOPED_LOCKABLE \ |
| 909 | THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable) |
| 910 | |
| 911 | // Replaced by ACQUIRE |
| 912 | #define EXCLUSIVE_LOCK_FUNCTION(...) \ |
| 913 | THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(__VA_ARGS__)) |
| 914 | |
| 915 | // Replaced by ACQUIRE_SHARED |
| 916 | #define SHARED_LOCK_FUNCTION(...) \ |
| 917 | THREAD_ANNOTATION_ATTRIBUTE__(shared_lock_function(__VA_ARGS__)) |
| 918 | |
| 919 | // Replaced by RELEASE and RELEASE_SHARED |
| 920 | #define UNLOCK_FUNCTION(...) \ |
| 921 | THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(__VA_ARGS__)) |
| 922 | |
| 923 | // Replaced by TRY_ACQUIRE |
| 924 | #define EXCLUSIVE_TRYLOCK_FUNCTION(...) \ |
| 925 | THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock_function(__VA_ARGS__)) |
| 926 | |
| 927 | // Replaced by TRY_ACQUIRE_SHARED |
| 928 | #define SHARED_TRYLOCK_FUNCTION(...) \ |
| 929 | THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock_function(__VA_ARGS__)) |
| 930 | |
| 931 | // Replaced by ASSERT_CAPABILITY |
| 932 | #define ASSERT_EXCLUSIVE_LOCK(...) \ |
| 933 | THREAD_ANNOTATION_ATTRIBUTE__(assert_exclusive_lock(__VA_ARGS__)) |
| 934 | |
| 935 | // Replaced by ASSERT_SHARED_CAPABILITY |
| 936 | #define ASSERT_SHARED_LOCK(...) \ |
| 937 | THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_lock(__VA_ARGS__)) |
| 938 | |
| 939 | // Replaced by EXCLUDE_CAPABILITY. |
| 940 | #define LOCKS_EXCLUDED(...) \ |
| 941 | THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__)) |
| 942 | |
| 943 | // Replaced by RETURN_CAPABILITY |
| 944 | #define LOCK_RETURNED(x) \ |
| 945 | THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) |
| 946 | |
| 947 | #endif // USE_LOCK_STYLE_THREAD_SAFETY_ATTRIBUTES |
| 948 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 949 | #endif // THREAD_SAFETY_ANALYSIS_MUTEX_H |
Stephen Hines | 176edba | 2014-12-01 14:53:08 -0800 | [diff] [blame] | 950 | |