|
6 | 6 | #ifndef _LINUX_COMPILER_CAPABILITY_ANALYSIS_H |
7 | 7 | #define _LINUX_COMPILER_CAPABILITY_ANALYSIS_H |
8 | 8 |
|
| 9 | +#if defined(WARN_CAPABILITY_ANALYSIS) |
| 10 | + |
| 11 | +/* |
| 12 | + * Tells the compiler to not do any capability analysis. Prefer |
| 13 | + * capability_unsafe(..) where possible. |
| 14 | + */ |
| 15 | +# define __no_capability_analysis __attribute__((no_thread_safety_analysis)) |
| 16 | + |
| 17 | +/* |
| 18 | + * The below attributes are used to define new capability types. |
| 19 | + */ |
| 20 | +# define __cap_type(name) __attribute__((capability(#name))) |
| 21 | +# define __acquires_cap(var) __attribute__((acquire_capability(var))) |
| 22 | +# define __acquires_shared_cap(var) __attribute__((acquire_shared_capability(var))) |
| 23 | +# define __try_acquires_cap(ret, var) __attribute__((try_acquire_capability(ret, var))) |
| 24 | +# define __try_acquires_shared_cap(ret, var) __attribute__((try_acquire_shared_capability(ret, var))) |
| 25 | +# define __releases_cap(var) __attribute__((release_capability(var))) |
| 26 | +# define __releases_shared_cap(var) __attribute__((release_shared_capability(var))) |
| 27 | +# define __asserts_cap(var) __attribute__((assert_capability(var))) |
| 28 | +# define __asserts_shared_cap(var) __attribute__((assert_shared_capability(var))) |
| 29 | +# define __returns_cap(var) __attribute__((lock_returned(var))) |
| 30 | + |
| 31 | +/* |
| 32 | + * The below are used to annotate code being checked. |
| 33 | + */ |
| 34 | +# define __var_guarded_by(var) __attribute__((guarded_by(var))) |
| 35 | +# define __ref_guarded_by(var) __attribute__((pt_guarded_by(var))) |
| 36 | +# define __excludes_cap(var) __attribute__((locks_excluded(var))) |
| 37 | +# define __requires_cap(var) __attribute__((requires_capability(var))) |
| 38 | +# define __requires_shared_cap(var) __attribute__((requires_shared_capability(var))) |
| 39 | + |
| 40 | +/* |
| 41 | + * Convenience helper to name a type with capability of the same name. |
| 42 | + * TODO: explain this |
| 43 | + */ |
| 44 | +# define struct_with_capability(name) \ |
| 45 | + struct __cap_type(name) name; \ |
| 46 | + static __always_inline void __acquire_cap(const struct name *var) \ |
| 47 | + __attribute__((overloadable)) __no_capability_analysis __acquires_cap(var) { } \ |
| 48 | + static __always_inline void __acquire_shared_cap(const struct name *var) \ |
| 49 | + __attribute__((overloadable)) __no_capability_analysis __acquires_shared_cap(var) { } \ |
| 50 | + static __always_inline bool __try_acquire_cap(const struct name *var, bool ret) \ |
| 51 | + __attribute__((overloadable)) __no_capability_analysis __try_acquires_cap(1, var) \ |
| 52 | + { return ret; } \ |
| 53 | + static __always_inline bool __try_acquire_shared_cap(const struct name *var, bool ret) \ |
| 54 | + __attribute__((overloadable)) __no_capability_analysis __try_acquires_shared_cap(1, var) \ |
| 55 | + { return ret; } \ |
| 56 | + static __always_inline void __release_cap(const struct name *var) \ |
| 57 | + __attribute__((overloadable)) __no_capability_analysis __releases_cap(var) { } \ |
| 58 | + static __always_inline void __release_shared_cap(const struct name *var) \ |
| 59 | + __attribute__((overloadable)) __no_capability_analysis __releases_shared_cap(var) { } \ |
| 60 | + static __always_inline void __assert_cap(const struct name *var) \ |
| 61 | + __attribute__((overloadable)) __asserts_cap(var) { } \ |
| 62 | + static __always_inline void __assert_shared_cap(const struct name *var) \ |
| 63 | + __attribute__((overloadable)) __asserts_shared_cap(var) { } \ |
| 64 | + struct name |
| 65 | + |
| 66 | +/* |
| 67 | + * TODO: |
| 68 | + */ |
| 69 | +# define disable_capability_analysis() \ |
| 70 | + __diag_push(); \ |
| 71 | + __diag_ignore_all("-Wunknown-warning-option", "") \ |
| 72 | + __diag_ignore_all("-Wthread-safety", "") \ |
| 73 | + __diag_ignore_all("-Wthread-safety-addressof", "") |
| 74 | + |
| 75 | +/* |
| 76 | + * TODO: |
| 77 | + */ |
| 78 | +# define enable_capability_analysis() __diag_pop() |
| 79 | + |
| 80 | +#else /* !WARN_CAPABILITY_ANALYSIS */ |
| 81 | + |
| 82 | +# define __no_capability_analysis |
| 83 | +# define __cap_type(name) |
| 84 | +# define __acquires_cap(var) |
| 85 | +# define __acquires_shared_cap(var) |
| 86 | +# define __try_acquires_cap(ret, var) |
| 87 | +# define __try_acquires_shared_cap(ret, var) |
| 88 | +# define __releases_cap(var) |
| 89 | +# define __releases_shared_cap(var) |
| 90 | +# define __asserts_cap(var) |
| 91 | +# define __asserts_shared_cap(var) |
| 92 | +# define __returns_cap(var) |
| 93 | +# define __var_guarded_by(var) |
| 94 | +# define __ref_guarded_by(var) |
| 95 | +# define __excludes_cap(var) |
| 96 | +# define __requires_cap(var) |
| 97 | +# define __requires_shared_cap(var) |
| 98 | +# define __acquire_cap(var) do { } while (0) |
| 99 | +# define __acquire_shared_cap(var) do { } while (0) |
| 100 | +# define __try_acquire_cap(var, ret) (ret) |
| 101 | +# define __try_acquire_shared_cap(var, ret) (ret) |
| 102 | +# define __release_cap(var) do { } while (0) |
| 103 | +# define __release_shared_cap(var) do { } while (0) |
| 104 | +# define __assert_cap(var) do { (void)(var); } while (0) |
| 105 | +# define __assert_shared_cap(var) do { (void)(var); } while (0) |
| 106 | +# define struct_with_capability(name) struct name |
| 107 | +# define disable_capability_analysis() |
| 108 | +# define enable_capability_analysis() |
| 109 | + |
| 110 | +#endif /* WARN_CAPABILITY_ANALYSIS */ |
| 111 | + |
| 112 | +/* |
| 113 | + * TODO: explain |
| 114 | + * |
| 115 | + * Works with any void or non-void expression. |
| 116 | + */ |
| 117 | +#define capability_unsafe(...) \ |
| 118 | +({ \ |
| 119 | + disable_capability_analysis(); \ |
| 120 | + __VA_ARGS__; \ |
| 121 | + enable_capability_analysis() \ |
| 122 | +}) |
| 123 | + |
| 124 | +/* |
| 125 | + * An abstract global capability used as a token, but not backed by a real data |
| 126 | + * structure (linker error if accidentally used). |
| 127 | + */ |
| 128 | +#define token_capability(name) \ |
| 129 | + struct_with_capability(__capability_##name) {}; \ |
| 130 | + extern const struct __capability_##name *name |
| 131 | +/* |
| 132 | + * To define additional instances of the same token capability. |
| 133 | + */ |
| 134 | +#define token_capability_instance(cap, name) \ |
| 135 | + extern const struct __capability_##cap *name |
| 136 | + |
| 137 | +/* |
| 138 | + * Common keywords for static capability analysis. Both Clang's capability |
| 139 | + * analysis and Sparse's context tracking are currently supported. |
| 140 | + */ |
9 | 141 | #ifdef __CHECKER__ |
10 | 142 |
|
11 | 143 | /* Sparse context/lock checking support. */ |
12 | 144 | # define __must_hold(x) __attribute__((context(x,1,1))) |
| 145 | +# define __must_not_hold(x) |
13 | 146 | # define __acquires(x) __attribute__((context(x,0,1))) |
14 | 147 | # define __cond_acquires(x) __attribute__((context(x,0,-1))) |
15 | 148 | # define __releases(x) __attribute__((context(x,1,0))) |
16 | 149 | # define __acquire(x) __context__(x,1) |
17 | 150 | # define __release(x) __context__(x,-1) |
18 | 151 | # define __cond_acquire(x, c) ((c) ? ({ __acquire(x); 1; }) : 0) |
| 152 | +/* For Sparse, there's no distinction between exclusive and shared locks. */ |
| 153 | +# define __must_hold_shared __must_hold |
| 154 | +# define __acquires_shared __acquires |
| 155 | +# define __cond_acquires_shared __cond_acquires |
| 156 | +# define __releases_shared __releases |
| 157 | +# define __acquire_shared __acquire |
| 158 | +# define __release_shared __release |
| 159 | +# define __cond_acquire_shared __cond_acquire |
19 | 160 |
|
20 | 161 | #else /* !__CHECKER__ */ |
21 | 162 |
|
22 | | -# define __must_hold(x) |
23 | | -# define __acquires(x) |
24 | | -# define __cond_acquires(x) |
25 | | -# define __releases(x) |
26 | | -# define __acquire(x) (void)0 |
27 | | -# define __release(x) (void)0 |
28 | | -# define __cond_acquire(x, c) (c) |
| 163 | +# define __must_hold(x) __requires_cap(x) |
| 164 | +# define __must_not_hold(x) __excludes_cap(x) |
| 165 | +# define __acquires(x) __acquires_cap(x) |
| 166 | +# define __cond_acquires(x) __try_acquires_cap(1, x) |
| 167 | +# define __releases(x) __releases_cap(x) |
| 168 | +# define __acquire(x) __acquire_cap(x) |
| 169 | +# define __release(x) __release_cap(x) |
| 170 | +# define __cond_acquire(x, c) __try_acquire_cap(x, c) |
| 171 | +# define __must_hold_shared(x) __requires_shared_cap(x) |
| 172 | +# define __acquires_shared(x) __acquires_shared_cap(x) |
| 173 | +# define __cond_acquires_shared(x) __try_acquires_shared_cap(1, x) |
| 174 | +# define __releases_shared(x) __releases_shared_cap(x) |
| 175 | +# define __acquire_shared(x) __acquire_shared_cap(x) |
| 176 | +# define __release_shared(x) __release_shared_cap(x) |
| 177 | +# define __cond_acquire_shared(x, c) __try_acquire_shared_cap(x, c) |
29 | 178 |
|
30 | 179 | #endif /* __CHECKER__ */ |
31 | 180 |
|
|
0 commit comments