XenevaOS
Loading...
Searching...
No Matches
compiler-context-analysis.h
Go to the documentation of this file.
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Macros and attributes for compiler-based static context analysis.
4 */
5
6#ifndef _LINUX_COMPILER_CONTEXT_ANALYSIS_H
7#define _LINUX_COMPILER_CONTEXT_ANALYSIS_H
8
9#if defined(WARN_CONTEXT_ANALYSIS) && !defined(__CHECKER__) && !defined(__GENKSYMS__)
10
11/*
12 * These attributes define new context lock (Clang: capability) types.
13 * Internal only.
14 */
15# define __ctx_lock_type(name) __attribute__((capability(#name)))
16# define __reentrant_ctx_lock __attribute__((reentrant_capability))
17# define __acquires_ctx_lock(...) __attribute__((acquire_capability(__VA_ARGS__)))
18# define __acquires_shared_ctx_lock(...) __attribute__((acquire_shared_capability(__VA_ARGS__)))
19# define __try_acquires_ctx_lock(ret, var) __attribute__((try_acquire_capability(ret, var)))
20# define __try_acquires_shared_ctx_lock(ret, var) __attribute__((try_acquire_shared_capability(ret, var)))
21# define __releases_ctx_lock(...) __attribute__((release_capability(__VA_ARGS__)))
22# define __releases_shared_ctx_lock(...) __attribute__((release_shared_capability(__VA_ARGS__)))
23# define __returns_ctx_lock(var) __attribute__((lock_returned(var)))
24
25/*
26 * The below are used to annotate code being checked. Internal only.
27 */
28# define __excludes_ctx_lock(...) __attribute__((locks_excluded(__VA_ARGS__)))
29# define __requires_ctx_lock(...) __attribute__((requires_capability(__VA_ARGS__)))
30# define __requires_shared_ctx_lock(...) __attribute__((requires_shared_capability(__VA_ARGS__)))
31
32/*
33 * The "assert_capability" attribute is a bit confusingly named. It does not
34 * generate a check. Instead, it tells the analysis to *assume* the capability
35 * is held. This is used for augmenting runtime assertions, that can then help
36 * with patterns beyond the compiler's static reasoning abilities.
37 */
38# define __assumes_ctx_lock(...) __attribute__((assert_capability(__VA_ARGS__)))
39# define __assumes_shared_ctx_lock(...) __attribute__((assert_shared_capability(__VA_ARGS__)))
40
63# define __guarded_by(...) __attribute__((guarded_by(__VA_ARGS__)))
64
88# define __pt_guarded_by(...) __attribute__((pt_guarded_by(__VA_ARGS__)))
89
112# define context_lock_struct(name, ...) \
113 struct __ctx_lock_type(name) __VA_ARGS__ name; \
114 static __always_inline void __acquire_ctx_lock(const struct name *var) \
115 __attribute__((overloadable)) __no_context_analysis __acquires_ctx_lock(var) { } \
116 static __always_inline void __acquire_shared_ctx_lock(const struct name *var) \
117 __attribute__((overloadable)) __no_context_analysis __acquires_shared_ctx_lock(var) { } \
118 static __always_inline bool __try_acquire_ctx_lock(const struct name *var, bool ret) \
119 __attribute__((overloadable)) __no_context_analysis __try_acquires_ctx_lock(1, var) \
120 { return ret; } \
121 static __always_inline bool __try_acquire_shared_ctx_lock(const struct name *var, bool ret) \
122 __attribute__((overloadable)) __no_context_analysis __try_acquires_shared_ctx_lock(1, var) \
123 { return ret; } \
124 static __always_inline void __release_ctx_lock(const struct name *var) \
125 __attribute__((overloadable)) __no_context_analysis __releases_ctx_lock(var) { } \
126 static __always_inline void __release_shared_ctx_lock(const struct name *var) \
127 __attribute__((overloadable)) __no_context_analysis __releases_shared_ctx_lock(var) { } \
128 static __always_inline void __assume_ctx_lock(const struct name *var) \
129 __attribute__((overloadable)) __assumes_ctx_lock(var) { } \
130 static __always_inline void __assume_shared_ctx_lock(const struct name *var) \
131 __attribute__((overloadable)) __assumes_shared_ctx_lock(var) { } \
132 struct name
133
140# define disable_context_analysis() \
141 __diag_push(); \
142 __diag_ignore_all("-Wunknown-warning-option", "") \
143 __diag_ignore_all("-Wthread-safety", "") \
144 __diag_ignore_all("-Wthread-safety-pointer", "")
145
152# define enable_context_analysis() __diag_pop()
153
160# define __no_context_analysis __attribute__((no_thread_safety_analysis))
161
162#else /* !WARN_CONTEXT_ANALYSIS */
163
164# define __ctx_lock_type(name)
165# define __reentrant_ctx_lock
166# define __acquires_ctx_lock(...)
167# define __acquires_shared_ctx_lock(...)
168# define __try_acquires_ctx_lock(ret, var)
169# define __try_acquires_shared_ctx_lock(ret, var)
170# define __releases_ctx_lock(...)
171# define __releases_shared_ctx_lock(...)
172# define __assumes_ctx_lock(...)
173# define __assumes_shared_ctx_lock(...)
174# define __returns_ctx_lock(var)
175# define __guarded_by(...)
176# define __pt_guarded_by(...)
177# define __excludes_ctx_lock(...)
178# define __requires_ctx_lock(...)
179# define __requires_shared_ctx_lock(...)
180# define __acquire_ctx_lock(var) do { } while (0)
181# define __acquire_shared_ctx_lock(var) do { } while (0)
182# define __try_acquire_ctx_lock(var, ret) (ret)
183# define __try_acquire_shared_ctx_lock(var, ret) (ret)
184# define __release_ctx_lock(var) do { } while (0)
185# define __release_shared_ctx_lock(var) do { } while (0)
186# define __assume_ctx_lock(var) do { (void)(var); } while (0)
187# define __assume_shared_ctx_lock(var) do { (void)(var); } while (0)
188# define context_lock_struct(name, ...) struct __VA_ARGS__ name
189# define disable_context_analysis()
190# define enable_context_analysis()
191# define __no_context_analysis
192
193#endif /* WARN_CONTEXT_ANALYSIS */
194
215#define context_unsafe(...) \
216({ \
217 disable_context_analysis(); \
218 __VA_ARGS__; \
219 enable_context_analysis() \
220})
221
229#define __context_unsafe(comment) __no_context_analysis
230
245#define context_unsafe_alias(p) _context_unsafe_alias((void **)&(p))
246static inline void _context_unsafe_alias(void **p) { }
247
256#define token_context_lock(name, ...) \
257 context_lock_struct(__ctx_lock_##name, ##__VA_ARGS__) {}; \
258 extern const struct __ctx_lock_##name *name
259
270#define token_context_lock_instance(ctx, name) \
271 extern const struct __ctx_lock_##ctx *name
272
273/*
274 * Common keywords for static context analysis.
275 */
276
283#define __must_hold(...) __requires_ctx_lock(__VA_ARGS__)
284
291#define __must_not_hold(...) __excludes_ctx_lock(__VA_ARGS__)
292
299#define __acquires(...) __acquires_ctx_lock(__VA_ARGS__)
300
301/*
302 * Clang's analysis does not care precisely about the value, only that it is
303 * either zero or non-zero. So the __cond_acquires() interface might be
304 * misleading if we say that @ret is the value returned if acquired. Instead,
305 * provide symbolic variants which we translate.
306 */
307#define __cond_acquires_impl_true(x, ...) __try_acquires##__VA_ARGS__##_ctx_lock(1, x)
308#define __cond_acquires_impl_false(x, ...) __try_acquires##__VA_ARGS__##_ctx_lock(0, x)
309#define __cond_acquires_impl_nonzero(x, ...) __try_acquires##__VA_ARGS__##_ctx_lock(1, x)
310#define __cond_acquires_impl_0(x, ...) __try_acquires##__VA_ARGS__##_ctx_lock(0, x)
311#define __cond_acquires_impl_nonnull(x, ...) __try_acquires##__VA_ARGS__##_ctx_lock(1, x)
312#define __cond_acquires_impl_NULL(x, ...) __try_acquires##__VA_ARGS__##_ctx_lock(0, x)
313
326#define __cond_acquires(ret, x) __cond_acquires_impl_##ret(x)
327
335#define __releases(...) __releases_ctx_lock(__VA_ARGS__)
336
337/*
338 * Clang's analysis does not care precisely about the value, only that it is
339 * either zero or non-zero. So the __cond_acquires() interface might be
340 * misleading if we say that @ret is the value returned if acquired. Instead,
341 * provide symbolic variants which we translate.
342 */
343#define __cond_acquires_impl_not_true(x, ...) __try_acquires##__VA_ARGS__##_ctx_lock(0, x)
344#define __cond_acquires_impl_not_false(x, ...) __try_acquires##__VA_ARGS__##_ctx_lock(1, x)
345#define __cond_acquires_impl_not_nonzero(x, ...) __try_acquires##__VA_ARGS__##_ctx_lock(0, x)
346#define __cond_acquires_impl_not_0(x, ...) __try_acquires##__VA_ARGS__##_ctx_lock(1, x)
347#define __cond_acquires_impl_not_nonnull(x, ...) __try_acquires##__VA_ARGS__##_ctx_lock(0, x)
348#define __cond_acquires_impl_not_NULL(x, ...) __try_acquires##__VA_ARGS__##_ctx_lock(1, x)
349
367#define __cond_releases(ret, x) __releases(x) __cond_acquires_impl_not_##ret(x)
368
375#define __acquire(x) __acquire_ctx_lock(x)
376
383#define __release(x) __release_ctx_lock(x)
384
391#define __must_hold_shared(...) __requires_shared_ctx_lock(__VA_ARGS__)
392
399#define __acquires_shared(...) __acquires_shared_ctx_lock(__VA_ARGS__)
400
413#define __cond_acquires_shared(ret, x) __cond_acquires_impl_##ret(x, _shared)
414
423#define __releases_shared(...) __releases_shared_ctx_lock(__VA_ARGS__)
424
432#define __acquire_shared(x) __acquire_shared_ctx_lock(x)
433
441#define __release_shared(x) __release_shared_ctx_lock(x)
442
448#define __acquire_ret(call, ret_expr) \
449 ({ \
450 __auto_type __ret = call; \
451 __acquire(ret_expr); \
452 __ret; \
453 })
454
460#define __acquire_shared_ret(call, ret_expr) \
461 ({ \
462 __auto_type __ret = call; \
463 __acquire_shared(ret_expr); \
464 __ret; \
465 })
466
467/*
468 * Attributes to mark functions returning acquired context locks.
469 *
470 * This is purely cosmetic to help readability, and should be used with the
471 * above macros as follows:
472 *
473 * struct foo { spinlock_t lock; ... };
474 * ...
475 * #define myfunc(...) __acquire_ret(_myfunc(__VA_ARGS__), &__ret->lock)
476 * struct foo *_myfunc(int bar) __acquires_ret;
477 * ...
478 */
479#define __acquires_ret __no_context_analysis
480#define __acquires_shared_ret __no_context_analysis
481
482#endif /* _LINUX_COMPILER_CONTEXT_ANALYSIS_H */