Message ID | 20250304092417.2873893-2-elver@google.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | Compiler-Based Capability- and Locking-Analysis | expand |
On 3/4/25 1:21 AM, Marco Elver wrote: > The conditional definition of lock checking macros and attributes is > about to become more complex. Factor them out into their own header for > better readability, and to make it obvious which features are supported > by which mode (currently only Sparse). This is the first step towards > generalizing towards "capability analysis". Reviewed-by: Bart Van Assche <bvanassche@acm.org>
On Tue, Mar 04, 2025 at 10:21:00AM +0100, Marco Elver wrote: > +#ifndef _LINUX_COMPILER_CAPABILITY_ANALYSIS_H > +#define _LINUX_COMPILER_CAPABILITY_ANALYSIS_H > + > +#ifdef __CHECKER__ > + > +/* Sparse context/lock checking support. */ > +# define __must_hold(x) __attribute__((context(x,1,1))) > +# define __acquires(x) __attribute__((context(x,0,1))) > +# define __cond_acquires(x) __attribute__((context(x,0,-1))) > +# define __releases(x) __attribute__((context(x,1,0))) > +# define __acquire(x) __context__(x,1) > +# define __release(x) __context__(x,-1) > +# define __cond_lock(x, c) ((c) ? ({ __acquire(x); 1; }) : 0) > + The other thing you might want to annotate is ww_mutex_destroy(). I'm happy about the new __guarded_by annotation. regards, dan carpenter
On Wed, Mar 05, 2025 at 11:36AM +0300, Dan Carpenter wrote: > On Tue, Mar 04, 2025 at 10:21:00AM +0100, Marco Elver wrote: > > +#ifndef _LINUX_COMPILER_CAPABILITY_ANALYSIS_H > > +#define _LINUX_COMPILER_CAPABILITY_ANALYSIS_H > > + > > +#ifdef __CHECKER__ > > + > > +/* Sparse context/lock checking support. */ > > +# define __must_hold(x) __attribute__((context(x,1,1))) > > +# define __acquires(x) __attribute__((context(x,0,1))) > > +# define __cond_acquires(x) __attribute__((context(x,0,-1))) > > +# define __releases(x) __attribute__((context(x,1,0))) > > +# define __acquire(x) __context__(x,1) > > +# define __release(x) __context__(x,-1) > > +# define __cond_lock(x, c) ((c) ? ({ __acquire(x); 1; }) : 0) > > + > > The other thing you might want to annotate is ww_mutex_destroy(). We can add an annotation to check the lock is not held: diff --git a/include/linux/ww_mutex.h b/include/linux/ww_mutex.h index 63978cb36a98..549d75aee76a 100644 --- a/include/linux/ww_mutex.h +++ b/include/linux/ww_mutex.h @@ -372,6 +372,7 @@ extern int __must_check ww_mutex_trylock(struct ww_mutex *lock, * this function is called. */ static inline void ww_mutex_destroy(struct ww_mutex *lock) + __must_not_hold(lock) { #ifndef CONFIG_PREEMPT_RT mutex_destroy(&lock->base); diff --git a/lib/test_capability-analysis.c b/lib/test_capability-analysis.c index 13e7732c38a2..1a466b362373 100644 --- a/lib/test_capability-analysis.c +++ b/lib/test_capability-analysis.c @@ -516,6 +516,8 @@ static void __used test_ww_mutex_lock_noctx(struct test_ww_mutex_data *d) ww_mutex_lock_slow(&d->mtx, NULL); d->counter++; ww_mutex_unlock(&d->mtx); + + ww_mutex_destroy(&d->mtx); } static void __used test_ww_mutex_lock_ctx(struct test_ww_mutex_data *d) @@ -545,4 +547,6 @@ static void __used test_ww_mutex_lock_ctx(struct test_ww_mutex_data *d) ww_acquire_done(&ctx); ww_acquire_fini(&ctx); + + ww_mutex_destroy(&d->mtx); } Probably a fixup for the ww_mutex patch: https://lore.kernel.org/all/20250304092417.2873893-21-elver@google.com/ Or extra patch depending on when/if Peter decides to take the series. > I'm happy about the new __guarded_by annotation. Thanks! -- Marco
On Wed, Mar 05, 2025 at 10:13:44AM +0100, Marco Elver wrote: > On Wed, Mar 05, 2025 at 11:36AM +0300, Dan Carpenter wrote: > > On Tue, Mar 04, 2025 at 10:21:00AM +0100, Marco Elver wrote: > > > +#ifndef _LINUX_COMPILER_CAPABILITY_ANALYSIS_H > > > +#define _LINUX_COMPILER_CAPABILITY_ANALYSIS_H > > > + > > > +#ifdef __CHECKER__ > > > + > > > +/* Sparse context/lock checking support. */ > > > +# define __must_hold(x) __attribute__((context(x,1,1))) > > > +# define __acquires(x) __attribute__((context(x,0,1))) > > > +# define __cond_acquires(x) __attribute__((context(x,0,-1))) > > > +# define __releases(x) __attribute__((context(x,1,0))) > > > +# define __acquire(x) __context__(x,1) > > > +# define __release(x) __context__(x,-1) > > > +# define __cond_lock(x, c) ((c) ? ({ __acquire(x); 1; }) : 0) > > > + > > > > The other thing you might want to annotate is ww_mutex_destroy(). > > We can add an annotation to check the lock is not held: > Sorry, my email was bad. I haven't actually tried your patch at all. I have locking check in Smatch so I'm just basing this on the things that I did... https://github.com/error27/smatch/blob/master/smatch_locking.c This isn't a mandatory thing. Whatever happens we're going to end up doing dozens of patches all over the kernel later. I thought you could destroy a mutex regardless or whether it was held or not. I was getting false positives which said that we should drop the lock on error but actually the mutex is destroyed on that path so it doesn't matter. regards, dan carpenter
diff --git a/include/linux/compiler-capability-analysis.h b/include/linux/compiler-capability-analysis.h new file mode 100644 index 000000000000..7546ddb83f86 --- /dev/null +++ b/include/linux/compiler-capability-analysis.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Macros and attributes for compiler-based static capability analysis. + */ + +#ifndef _LINUX_COMPILER_CAPABILITY_ANALYSIS_H +#define _LINUX_COMPILER_CAPABILITY_ANALYSIS_H + +#ifdef __CHECKER__ + +/* Sparse context/lock checking support. */ +# define __must_hold(x) __attribute__((context(x,1,1))) +# define __acquires(x) __attribute__((context(x,0,1))) +# define __cond_acquires(x) __attribute__((context(x,0,-1))) +# define __releases(x) __attribute__((context(x,1,0))) +# define __acquire(x) __context__(x,1) +# define __release(x) __context__(x,-1) +# define __cond_lock(x, c) ((c) ? ({ __acquire(x); 1; }) : 0) + +#else /* !__CHECKER__ */ + +# define __must_hold(x) +# define __acquires(x) +# define __cond_acquires(x) +# define __releases(x) +# define __acquire(x) (void)0 +# define __release(x) (void)0 +# define __cond_lock(x, c) (c) + +#endif /* __CHECKER__ */ + +#endif /* _LINUX_COMPILER_CAPABILITY_ANALYSIS_H */ diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h index 981cc3d7e3aa..4a458e41293c 100644 --- a/include/linux/compiler_types.h +++ b/include/linux/compiler_types.h @@ -24,6 +24,8 @@ # define BTF_TYPE_TAG(value) /* nothing */ #endif +#include <linux/compiler-capability-analysis.h> + /* sparse defines __CHECKER__; see Documentation/dev-tools/sparse.rst */ #ifdef __CHECKER__ /* address spaces */ @@ -34,14 +36,6 @@ # define __rcu __attribute__((noderef, address_space(__rcu))) static inline void __chk_user_ptr(const volatile void __user *ptr) { } static inline void __chk_io_ptr(const volatile void __iomem *ptr) { } -/* context/locking */ -# define __must_hold(x) __attribute__((context(x,1,1))) -# define __acquires(x) __attribute__((context(x,0,1))) -# define __cond_acquires(x) __attribute__((context(x,0,-1))) -# define __releases(x) __attribute__((context(x,1,0))) -# define __acquire(x) __context__(x,1) -# define __release(x) __context__(x,-1) -# define __cond_lock(x,c) ((c) ? ({ __acquire(x); 1; }) : 0) /* other */ # define __force __attribute__((force)) # define __nocast __attribute__((nocast)) @@ -62,14 +56,6 @@ static inline void __chk_io_ptr(const volatile void __iomem *ptr) { } # define __chk_user_ptr(x) (void)0 # define __chk_io_ptr(x) (void)0 -/* context/locking */ -# define __must_hold(x) -# define __acquires(x) -# define __cond_acquires(x) -# define __releases(x) -# define __acquire(x) (void)0 -# define __release(x) (void)0 -# define __cond_lock(x,c) (c) /* other */ # define __force # define __nocast
The conditional definition of lock checking macros and attributes is about to become more complex. Factor them out into their own header for better readability, and to make it obvious which features are supported by which mode (currently only Sparse). This is the first step towards generalizing towards "capability analysis". No functional change intended. Signed-off-by: Marco Elver <elver@google.com> --- include/linux/compiler-capability-analysis.h | 32 ++++++++++++++++++++ include/linux/compiler_types.h | 18 ++--------- 2 files changed, 34 insertions(+), 16 deletions(-) create mode 100644 include/linux/compiler-capability-analysis.h