|
| 1 | +.. SPDX-License-Identifier: GPL-2.0 |
| 2 | +.. Copyright (C) 2025, Google LLC. |
| 3 | +
|
| 4 | +.. _context-analysis: |
| 5 | + |
| 6 | +Compiler-Based Context Analysis |
| 7 | +=============================== |
| 8 | + |
| 9 | +Context Analysis is a language extension, which enables statically checking |
| 10 | +that required contexts are active (or inactive) by acquiring and releasing |
| 11 | +user-definable "context locks". An obvious application is lock-safety checking |
| 12 | +for the kernel's various synchronization primitives (each of which represents a |
| 13 | +"context lock"), and checking that locking rules are not violated. |
| 14 | + |
| 15 | +The Clang compiler currently supports the full set of context analysis |
| 16 | +features. To enable for Clang, configure the kernel with:: |
| 17 | + |
| 18 | + CONFIG_WARN_CONTEXT_ANALYSIS=y |
| 19 | + |
| 20 | +The feature requires Clang 22 or later. |
| 21 | + |
| 22 | +The analysis is *opt-in by default*, and requires declaring which modules and |
| 23 | +subsystems should be analyzed in the respective `Makefile`:: |
| 24 | + |
| 25 | + CONTEXT_ANALYSIS_mymodule.o := y |
| 26 | + |
| 27 | +Or for all translation units in the directory:: |
| 28 | + |
| 29 | + CONTEXT_ANALYSIS := y |
| 30 | + |
| 31 | +It is possible to enable the analysis tree-wide, however, which will result in |
| 32 | +numerous false positive warnings currently and is *not* generally recommended:: |
| 33 | + |
| 34 | + CONFIG_WARN_CONTEXT_ANALYSIS_ALL=y |
| 35 | + |
| 36 | +Programming Model |
| 37 | +----------------- |
| 38 | + |
| 39 | +The below describes the programming model around using context lock types. |
| 40 | + |
| 41 | +.. note:: |
| 42 | + Enabling context analysis can be seen as enabling a dialect of Linux C with |
| 43 | + a Context System. Some valid patterns involving complex control-flow are |
| 44 | + constrained (such as conditional acquisition and later conditional release |
| 45 | + in the same function). |
| 46 | + |
| 47 | +Context analysis is a way to specify permissibility of operations to depend on |
| 48 | +context locks being held (or not held). Typically we are interested in |
| 49 | +protecting data and code in a critical section by requiring a specific context |
| 50 | +to be active, for example by holding a specific lock. The analysis ensures that |
| 51 | +callers cannot perform an operation without the required context being active. |
| 52 | + |
| 53 | +Context locks are associated with named structs, along with functions that |
| 54 | +operate on struct instances to acquire and release the associated context lock. |
| 55 | + |
| 56 | +Context locks can be held either exclusively or shared. This mechanism allows |
| 57 | +assigning more precise privileges when a context is active, typically to |
| 58 | +distinguish where a thread may only read (shared) or also write (exclusive) to |
| 59 | +data guarded within a context. |
| 60 | + |
| 61 | +The set of contexts that are actually active in a given thread at a given point |
| 62 | +in program execution is a run-time concept. The static analysis works by |
| 63 | +calculating an approximation of that set, called the context environment. The |
| 64 | +context environment is calculated for every program point, and describes the |
| 65 | +set of contexts that are statically known to be active, or inactive, at that |
| 66 | +particular point. This environment is a conservative approximation of the full |
| 67 | +set of contexts that will actually be active in a thread at run-time. |
| 68 | + |
| 69 | +More details are also documented `here |
| 70 | +<https://clang.llvm.org/docs/ThreadSafetyAnalysis.html>`_. |
| 71 | + |
| 72 | +.. note:: |
| 73 | + Clang's analysis explicitly does not infer context locks acquired or |
| 74 | + released by inline functions. It requires explicit annotations to (a) assert |
| 75 | + that it's not a bug if a context lock is released or acquired, and (b) to |
| 76 | + retain consistency between inline and non-inline function declarations. |
| 77 | + |
| 78 | +Supported Kernel Primitives |
| 79 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 80 | + |
| 81 | +Currently the following synchronization primitives are supported: |
| 82 | +`raw_spinlock_t`, `spinlock_t`, `rwlock_t`, `mutex`, `seqlock_t`, |
| 83 | +`bit_spinlock`, RCU, SRCU (`srcu_struct`), `rw_semaphore`, `local_lock_t`, |
| 84 | +`ww_mutex`. |
| 85 | + |
| 86 | +To initialize variables guarded by a context lock with an initialization |
| 87 | +function (``type_init(&lock)``), prefer using ``guard(type_init)(&lock)`` or |
| 88 | +``scoped_guard(type_init, &lock) { ... }`` to initialize such guarded members |
| 89 | +or globals in the enclosing scope. This initializes the context lock and treats |
| 90 | +the context as active within the initialization scope (initialization implies |
| 91 | +exclusive access to the underlying object). |
| 92 | + |
| 93 | +For example:: |
| 94 | + |
| 95 | + struct my_data { |
| 96 | + spinlock_t lock; |
| 97 | + int counter __guarded_by(&lock); |
| 98 | + }; |
| 99 | + |
| 100 | + void init_my_data(struct my_data *d) |
| 101 | + { |
| 102 | + ... |
| 103 | + guard(spinlock_init)(&d->lock); |
| 104 | + d->counter = 0; |
| 105 | + ... |
| 106 | + } |
| 107 | + |
| 108 | +Alternatively, initializing guarded variables can be done with context analysis |
| 109 | +disabled, preferably in the smallest possible scope (due to lack of any other |
| 110 | +checking): either with a ``context_unsafe(var = init)`` expression, or by |
| 111 | +marking small initialization functions with the ``__context_unsafe(init)`` |
| 112 | +attribute. |
| 113 | + |
| 114 | +Lockdep assertions, such as `lockdep_assert_held()`, inform the compiler's |
| 115 | +context analysis that the associated synchronization primitive is held after |
| 116 | +the assertion. This avoids false positives in complex control-flow scenarios |
| 117 | +and encourages the use of Lockdep where static analysis is limited. For |
| 118 | +example, this is useful when a function doesn't *always* require a lock, making |
| 119 | +`__must_hold()` inappropriate. |
| 120 | + |
| 121 | +Keywords |
| 122 | +~~~~~~~~ |
| 123 | + |
| 124 | +.. kernel-doc:: include/linux/compiler-context-analysis.h |
| 125 | + :identifiers: context_lock_struct |
| 126 | + token_context_lock token_context_lock_instance |
| 127 | + __guarded_by __pt_guarded_by |
| 128 | + __must_hold |
| 129 | + __must_not_hold |
| 130 | + __acquires |
| 131 | + __cond_acquires |
| 132 | + __releases |
| 133 | + __must_hold_shared |
| 134 | + __acquires_shared |
| 135 | + __cond_acquires_shared |
| 136 | + __releases_shared |
| 137 | + __acquire |
| 138 | + __release |
| 139 | + __acquire_shared |
| 140 | + __release_shared |
| 141 | + __acquire_ret |
| 142 | + __acquire_shared_ret |
| 143 | + context_unsafe |
| 144 | + __context_unsafe |
| 145 | + disable_context_analysis enable_context_analysis |
| 146 | + |
| 147 | +.. note:: |
| 148 | + The function attribute `__no_context_analysis` is reserved for internal |
| 149 | + implementation of context lock types, and should be avoided in normal code. |
| 150 | + |
| 151 | +Background |
| 152 | +---------- |
| 153 | + |
| 154 | +Clang originally called the feature `Thread Safety Analysis |
| 155 | +<https://clang.llvm.org/docs/ThreadSafetyAnalysis.html>`_, with some keywords |
| 156 | +and documentation still using the thread-safety-analysis-only terminology. This |
| 157 | +was later changed and the feature became more flexible, gaining the ability to |
| 158 | +define custom "capabilities". Its foundations can be found in `Capability |
| 159 | +Systems <https://www.cs.cornell.edu/talc/papers/capabilities.pdf>`_, used to |
| 160 | +specify the permissibility of operations to depend on some "capability" being |
| 161 | +held (or not held). |
| 162 | + |
| 163 | +Because the feature is not just able to express capabilities related to |
| 164 | +synchronization primitives, and "capability" is already overloaded in the |
| 165 | +kernel, the naming chosen for the kernel departs from Clang's initial "Thread |
| 166 | +Safety" and "capability" nomenclature; we refer to the feature as "Context |
| 167 | +Analysis" to avoid confusion. The internal implementation still makes |
| 168 | +references to Clang's terminology in a few places, such as `-Wthread-safety` |
| 169 | +being the warning option that also still appears in diagnostic messages. |
0 commit comments