Merge branch 'locking/context' into locking/core

This commit is contained in:
Peter Zijlstra
2026-05-28 12:23:39 +02:00
4 changed files with 49 additions and 11 deletions

View File

@@ -17,7 +17,7 @@ features. To enable for Clang, configure the kernel with::
CONFIG_WARN_CONTEXT_ANALYSIS=y
The feature requires Clang 22 or later.
The feature requires Clang 23 or later.
The analysis is *opt-in by default*, and requires declaring which modules and
subsystems should be analyzed in the respective `Makefile`::

View File

@@ -39,12 +39,14 @@
# define __assumes_shared_ctx_lock(...) __attribute__((assert_shared_capability(__VA_ARGS__)))
/**
* __guarded_by - struct member and globals attribute, declares variable
* only accessible within active context
* __guarded_by() - struct member and globals attribute, declares variable
* only accessible within active context
* @...: context lock instance pointer(s)
*
* Declares that the struct member or global variable is only accessible within
* the context entered by the given context lock. Read operations on the data
* require shared access, while write operations require exclusive access.
* the context entered by the given context lock(s). Read operations on the data
* require shared access to at least one of the context locks, while write
* operations require exclusive access to all listed context locks.
*
* .. code-block:: c
*
@@ -52,17 +54,24 @@
* spinlock_t lock;
* long counter __guarded_by(&lock);
* };
*
* struct some_state {
* spinlock_t lock1, lock2;
* long counter __guarded_by(&lock1, &lock2);
* };
*/
# define __guarded_by(...) __attribute__((guarded_by(__VA_ARGS__)))
/**
* __pt_guarded_by - struct member and globals attribute, declares pointed-to
* data only accessible within active context
* __pt_guarded_by() - struct member and globals attribute, declares pointed-to
* data only accessible within active context
* @...: context lock instance pointer(s)
*
* Declares that the data pointed to by the struct member pointer or global
* pointer is only accessible within the context entered by the given context
* lock. Read operations on the data require shared access, while write
* operations require exclusive access.
* lock(s). Read operations on the data require shared access to at least one
* of the context locks, while write operations require exclusive access to all
* listed context locks.
*
* .. code-block:: c
*
@@ -70,6 +79,11 @@
* spinlock_t lock;
* long *counter __pt_guarded_by(&lock);
* };
*
* struct some_state {
* spinlock_t lock1, lock2;
* long *counter __pt_guarded_by(&lock1, &lock2);
* };
*/
# define __pt_guarded_by(...) __attribute__((pt_guarded_by(__VA_ARGS__)))

View File

@@ -630,7 +630,7 @@ config DEBUG_FORCE_WEAK_PER_CPU
config WARN_CONTEXT_ANALYSIS
bool "Compiler context-analysis warnings"
depends on CC_IS_CLANG && CLANG_VERSION >= 220100
depends on CC_IS_CLANG && CLANG_VERSION >= 230000
# Branch profiling re-defines "if", which messes with the compiler's
# ability to analyze __cond_acquires(..), resulting in false positives.
depends on !TRACE_BRANCH_PROFILING
@@ -641,7 +641,7 @@ config WARN_CONTEXT_ANALYSIS
and releasing user-definable "context locks".
Clang's name of the feature is "Thread Safety Analysis". Requires
Clang 22.1.0 or later.
Clang 23 or later.
Produces warnings by default. Select CONFIG_WERROR if you wish to
turn these warnings into errors.

View File

@@ -159,6 +159,10 @@ TEST_SPINLOCK_COMMON(read_lock,
struct test_mutex_data {
struct mutex mtx;
int counter __guarded_by(&mtx);
struct mutex mtx2;
int anyread __guarded_by(&mtx, &mtx2);
int *anyptr __pt_guarded_by(&mtx, &mtx2);
};
static void __used test_mutex_init(struct test_mutex_data *d)
@@ -219,6 +223,26 @@ static void __used test_mutex_cond_guard(struct test_mutex_data *d)
}
}
static void __used test_mutex_multiguard(struct test_mutex_data *d)
{
mutex_lock(&d->mtx);
(void)d->anyread;
(void)*d->anyptr;
mutex_unlock(&d->mtx);
mutex_lock(&d->mtx2);
(void)d->anyread;
(void)*d->anyptr;
mutex_unlock(&d->mtx2);
mutex_lock(&d->mtx);
mutex_lock(&d->mtx2);
d->anyread++;
(*d->anyptr)++;
mutex_unlock(&d->mtx2);
mutex_unlock(&d->mtx);
}
struct test_seqlock_data {
seqlock_t sl;
int counter __guarded_by(&sl);