• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 //
15 // This header file contains macro definitions for thread safety annotations
16 // that allow developers to document the locking policies of multi-threaded
17 // code. The annotations can also help program analysis tools to identify
18 // potential thread safety issues.
19 //
20 // These annotations are implemented using compiler attributes. Using the macros
21 // defined here instead of raw attributes allow for portability and future
22 // compatibility.
23 //
24 // The thread safety analysis system is documented at
25 // http://clang.llvm.org/docs/ThreadSafetyAnalysis.html
26 //
27 // When referring to locks in the arguments of the attributes, you should
28 // use variable names or more complex expressions (e.g. my_object->lock_)
29 // that evaluate to a concrete lock object whenever possible. If the lock
30 // you want to refer to is not in scope, you may use a member pointer
31 // (e.g. &MyClass::lock_) to refer to a lock in some (unknown) object.
32 
33 #pragma once
34 
35 #include "pw_preprocessor/compiler.h"
36 
37 /// @def PW_GUARDED_BY
38 ///
39 /// Documents if a shared field or global variable needs to be protected by a
40 /// lock. `PW_GUARDED_BY()` allows the user to specify a particular lock that
41 /// should be held when accessing the annotated variable.
42 ///
43 /// Although this annotation (and `PW_PT_GUARDED_BY()`, below) cannot be applied
44 /// to local variables, a local variable and its associated lock can often be
45 /// combined into a small class or struct, thereby allowing the annotation.
46 ///
47 /// Example:
48 ///
49 /// @code
50 ///    class Foo {
51 ///      Mutex mu_;
52 ///      int p1_ PW_GUARDED_BY(mu_);
53 ///      ...
54 ///    };
55 /// @endcode
56 ///
57 #if PW_HAVE_ATTRIBUTE(guarded_by)
58 #define PW_GUARDED_BY(x) __attribute__((guarded_by(x)))
59 #else
60 #define PW_GUARDED_BY(x)
61 #endif
62 
63 /// @def PW_PT_GUARDED_BY
64 ///
65 /// Documents if the memory location pointed to by a pointer should be guarded
66 /// by a lock when dereferencing the pointer.
67 ///
68 /// Example:
69 ///
70 /// @code
71 ///    class Foo {
72 ///      Mutex mu_;
73 ///      int *p1_ PW_PT_GUARDED_BY(mu_);
74 ///      ...
75 ///    };
76 /// @endcode
77 ///
78 /// @note A pointer variable to a shared memory location could itself be a
79 /// shared variable.
80 ///
81 /// Example:
82 ///
83 /// @code
84 ///    // `q_`, guarded by `mu1_`, points to a shared memory location that is
85 ///    // guarded by `mu2_`:
86 ///    int *q_ PW_GUARDED_BY(mu1_) PW_PT_GUARDED_BY(mu2_);
87 /// @endcode
88 #if PW_HAVE_ATTRIBUTE(pt_guarded_by)
89 #define PW_PT_GUARDED_BY(x) __attribute__((pt_guarded_by(x)))
90 #else
91 #define PW_PT_GUARDED_BY(x)
92 #endif
93 
94 /// @def PW_ACQUIRED_AFTER
95 /// @def PW_ACQUIRED_BEFORE
96 ///
97 /// Documents the acquisition order between locks that can be held
98 /// simultaneously by a thread. For any two locks that need to be annotated
99 /// to establish an acquisition order, only one of them needs the annotation.
100 /// (i.e. You don't have to annotate both locks with both `PW_ACQUIRED_AFTER()`
101 /// and `PW_ACQUIRED_BEFORE()`.)
102 ///
103 /// As with `PW_GUARDED_BY()`, this is only applicable to locks that are shared
104 /// fields or global variables.
105 ///
106 /// Example:
107 ///
108 /// @code
109 ///   Mutex m1_;
110 ///   Mutex m2_ PW_ACQUIRED_AFTER(m1_);
111 /// @endcode
112 #if PW_HAVE_ATTRIBUTE(acquired_after)
113 #define PW_ACQUIRED_AFTER(...) __attribute__((acquired_after(__VA_ARGS__)))
114 #else
115 #define PW_ACQUIRED_AFTER(...)
116 #endif
117 
118 #if PW_HAVE_ATTRIBUTE(acquired_before)
119 #define PW_ACQUIRED_BEFORE(...) __attribute__((acquired_before(__VA_ARGS__)))
120 #else
121 #define PW_ACQUIRED_BEFORE(...)
122 #endif
123 
124 /// @def PW_EXCLUSIVE_LOCKS_REQUIRED
125 /// @def PW_SHARED_LOCKS_REQUIRED
126 ///
127 /// Documents a function that expects a lock to be held prior to entry.
128 /// The lock is expected to be held both on entry to, and exit from, the
129 /// function.
130 ///
131 /// An exclusive lock allows read-write access to the guarded data member(s),
132 /// and only one thread can acquire a lock exclusively at any one time. A shared
133 /// lock allows read-only access, and any number of threads can acquire a shared
134 /// lock concurrently.
135 ///
136 /// Generally, non-const methods should be annotated with
137 /// `PW_EXCLUSIVE_LOCKS_REQUIRED()`, while const methods should be annotated
138 /// with `PW_SHARED_LOCKS_REQUIRED()`.
139 ///
140 /// Example:
141 ///
142 /// @code
143 ///   Mutex mu1, mu2;
144 ///   int a PW_GUARDED_BY(mu1);
145 ///   int b PW_GUARDED_BY(mu2);
146 ///
147 ///   void foo() PW_EXCLUSIVE_LOCKS_REQUIRED(mu1, mu2) { ... }
148 ///   void bar() const PW_SHARED_LOCKS_REQUIRED(mu1, mu2) { ... }
149 /// @endcode
150 #if PW_HAVE_ATTRIBUTE(exclusive_locks_required)
151 #define PW_EXCLUSIVE_LOCKS_REQUIRED(...) \
152   __attribute__((exclusive_locks_required(__VA_ARGS__)))
153 #else
154 #define PW_EXCLUSIVE_LOCKS_REQUIRED(...)
155 #endif
156 
157 #if PW_HAVE_ATTRIBUTE(shared_locks_required)
158 #define PW_SHARED_LOCKS_REQUIRED(...) \
159   __attribute__((shared_locks_required(__VA_ARGS__)))
160 #else
161 #define PW_SHARED_LOCKS_REQUIRED(...)
162 #endif
163 
164 /// @def PW_LOCKS_EXCLUDED
165 ///
166 /// Documents that the caller must not hold the given lock. This annotation is
167 /// often used to prevent deadlocks. Pigweed's mutex implementation is not
168 /// re-entrant, so a deadlock will occur if the function acquires the mutex a
169 /// second time.
170 ///
171 /// Example:
172 ///
173 /// @code
174 ///   Mutex mu;
175 ///   int a PW_GUARDED_BY(mu);
176 ///
177 ///   void foo() PW_LOCKS_EXCLUDED(mu) {
178 ///     mu.lock();
179 ///     ...
180 ///     mu.unlock();
181 ///   }
182 /// @endcode
183 #if PW_HAVE_ATTRIBUTE(locks_excluded)
184 #define PW_LOCKS_EXCLUDED(...) __attribute__((locks_excluded(__VA_ARGS__)))
185 #else
186 #define PW_LOCKS_EXCLUDED(...)
187 #endif
188 
189 /// @def PW_LOCK_RETURNED
190 ///
191 /// Documents a function that returns a lock without acquiring it.  For example,
192 /// a public getter method that returns a pointer to a private lock should
193 /// be annotated with `PW_LOCK_RETURNED()`.
194 ///
195 /// Example:
196 ///
197 /// @code
198 ///   class Foo {
199 ///    public:
200 ///     Mutex* mu() PW_LOCK_RETURNED(mu) { return μ }
201 ///
202 ///    private:
203 ///     Mutex mu;
204 ///   };
205 /// @endcode
206 #if PW_HAVE_ATTRIBUTE(lock_returned)
207 #define PW_LOCK_RETURNED(x) __attribute__((lock_returned(x)))
208 #else
209 #define PW_LOCK_RETURNED(x)
210 #endif
211 
212 /// @def PW_LOCKABLE
213 ///
214 /// Documents if a class/type is a lockable type (such as the `pw::sync::Mutex`
215 /// class). The name is used in the warning messages. This can also be useful on
216 /// classes which have locking like semantics but aren't actually locks.
217 #if PW_HAVE_ATTRIBUTE(capability)
218 #define PW_LOCKABLE(name) __attribute__((capability(name)))
219 #elif PW_HAVE_ATTRIBUTE(lockable)
220 #define PW_LOCKABLE(name) __attribute__((lockable))
221 #else
222 #define PW_LOCKABLE(name)
223 #endif
224 
225 /// @def PW_SCOPED_LOCKABLE
226 ///
227 /// Documents if a class does RAII locking. The name is used in the warning
228 /// messages.
229 ///
230 /// The constructor should use `LOCK_FUNCTION()` to specify the lock that is
231 /// acquired, and the destructor should use `UNLOCK_FUNCTION()` with no
232 /// arguments; the analysis will assume that the destructor unlocks whatever the
233 /// constructor locked.
234 #if PW_HAVE_ATTRIBUTE(scoped_lockable)
235 #define PW_SCOPED_LOCKABLE __attribute__((scoped_lockable))
236 #else
237 #define PW_SCOPED_LOCKABLE
238 #endif
239 
240 /// @def PW_EXCLUSIVE_LOCK_FUNCTION
241 ///
242 /// Documents functions that acquire a lock in the body of a function, and do
243 /// not release it.
244 #if PW_HAVE_ATTRIBUTE(exclusive_lock_function)
245 #define PW_EXCLUSIVE_LOCK_FUNCTION(...) \
246   __attribute__((exclusive_lock_function(__VA_ARGS__)))
247 #else
248 #define PW_EXCLUSIVE_LOCK_FUNCTION(...)
249 #endif
250 
251 /// @def PW_SHARED_LOCK_FUNCTION
252 ///
253 /// Documents functions that acquire a shared (reader) lock in the body of a
254 /// function, and do not release it.
255 #if PW_HAVE_ATTRIBUTE(shared_lock_function)
256 #define PW_SHARED_LOCK_FUNCTION(...) \
257   __attribute__((shared_lock_function(__VA_ARGS__)))
258 #else
259 #define PW_SHARED_LOCK_FUNCTION(...)
260 #endif
261 
262 /// @def PW_UNLOCK_FUNCTION
263 ///
264 /// Documents functions that expect a lock to be held on entry to the function,
265 /// and release it in the body of the function.
266 #if PW_HAVE_ATTRIBUTE(unlock_function)
267 #define PW_UNLOCK_FUNCTION(...) __attribute__((unlock_function(__VA_ARGS__)))
268 #else
269 #define PW_UNLOCK_FUNCTION(...)
270 #endif
271 
272 /// @def PW_EXCLUSIVE_TRYLOCK_FUNCTION
273 /// @def PW_SHARED_TRYLOCK_FUNCTION
274 ///
275 /// Documents functions that try to acquire a lock, and return success or
276 /// failure (or a non-boolean value that can be interpreted as a boolean). The
277 /// first argument should be `true` for functions that return `true` on success,
278 /// or `false` for functions that return `false` on success. The second argument
279 /// specifies the lock that is locked on success. If unspecified, this lock is
280 /// assumed to be `this`.
281 #if PW_HAVE_ATTRIBUTE(exclusive_trylock_function)
282 #define PW_EXCLUSIVE_TRYLOCK_FUNCTION(...) \
283   __attribute__((exclusive_trylock_function(__VA_ARGS__)))
284 #else
285 #define PW_EXCLUSIVE_TRYLOCK_FUNCTION(...)
286 #endif
287 
288 #if PW_HAVE_ATTRIBUTE(shared_trylock_function)
289 #define PW_SHARED_TRYLOCK_FUNCTION(...) \
290   __attribute__((shared_trylock_function(__VA_ARGS__)))
291 #else
292 #define PW_SHARED_TRYLOCK_FUNCTION(...)
293 #endif
294 
295 /// @def PW_ASSERT_EXCLUSIVE_LOCK
296 /// @def PW_ASSERT_SHARED_LOCK
297 ///
298 /// Documents functions that dynamically check to see if a lock is held, and
299 /// fail if it is not held.
300 #if PW_HAVE_ATTRIBUTE(assert_exclusive_lock)
301 #define PW_ASSERT_EXCLUSIVE_LOCK(...) \
302   __attribute__((assert_exclusive_lock(__VA_ARGS__)))
303 #else
304 #define PW_ASSERT_EXCLUSIVE_LOCK(...)
305 #endif
306 
307 #if PW_HAVE_ATTRIBUTE(assert_shared_lock)
308 #define PW_ASSERT_SHARED_LOCK(...) \
309   __attribute__((assert_shared_lock(__VA_ARGS__)))
310 #else
311 #define PW_ASSERT_SHARED_LOCK(...)
312 #endif
313 
314 /// @def PW_NO_LOCK_SAFETY_ANALYSIS
315 ///
316 /// Turns off thread safety checking within the body of a particular function.
317 /// This annotation is used to mark functions that are known to be correct, but
318 /// the locking behavior is more complicated than the analyzer can handle.
319 #if PW_HAVE_ATTRIBUTE(no_thread_safety_analysis)
320 #define PW_NO_LOCK_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis))
321 #else
322 #define PW_NO_LOCK_SAFETY_ANALYSIS
323 #endif
324