| 1 | |
| 2 | |
| 3 |
|
| 4 | |
| 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 23 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.
|