Message ID | 20250206181711.1902989-2-elver@google.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | Compiler-Based Capability- and Locking-Analysis | expand |
On 2/6/25 10:09 AM, Marco Elver wrote: > +/* 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) If support for Clang thread-safety attributes is added, an important question is what to do with the sparse context attribute. I think that more developers are working on improving and maintaining Clang than sparse. How about reducing the workload of kernel maintainers by only supporting the Clang thread-safety approach and by dropping support for the sparse context attribute? Thanks, Bart.
On Thu, 6 Feb 2025 at 19:40, Bart Van Assche <bvanassche@acm.org> wrote: > > On 2/6/25 10:09 AM, Marco Elver wrote: > > +/* 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) > > If support for Clang thread-safety attributes is added, an important > question is what to do with the sparse context attribute. I think that > more developers are working on improving and maintaining Clang than > sparse. How about reducing the workload of kernel maintainers by > only supporting the Clang thread-safety approach and by dropping support > for the sparse context attribute? My 2c: I think Sparse's context tracking is a subset, and generally less complete, favoring false negatives over false positives (also does not support guarded_by). So in theory they can co-exist. In practice, I agree, there will be issues with maintaining both, because there will always be some odd corner-case which doesn't quite work with one or the other (specifically Sparse is happy to auto-infer acquired and released capabilities/contexts of functions and doesn't warn you if you still hold a lock when returning from a function). I'd be in favor of deprecating Sparse's context tracking support, should there be consensus on that. Thanks, -- Marco
On Thu, Feb 06, 2025 at 07:48:38PM +0100, Marco Elver wrote: > On Thu, 6 Feb 2025 at 19:40, Bart Van Assche <bvanassche@acm.org> wrote: > > > > On 2/6/25 10:09 AM, Marco Elver wrote: > > > +/* 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) > > > > If support for Clang thread-safety attributes is added, an important > > question is what to do with the sparse context attribute. I think that > > more developers are working on improving and maintaining Clang than > > sparse. How about reducing the workload of kernel maintainers by > > only supporting the Clang thread-safety approach and by dropping support > > for the sparse context attribute? > > My 2c: I think Sparse's context tracking is a subset, and generally > less complete, favoring false negatives over false positives (also > does not support guarded_by). > So in theory they can co-exist. > In practice, I agree, there will be issues with maintaining both, > because there will always be some odd corner-case which doesn't quite > work with one or the other (specifically Sparse is happy to auto-infer > acquired and released capabilities/contexts of functions and doesn't > warn you if you still hold a lock when returning from a function). > > I'd be in favor of deprecating Sparse's context tracking support, > should there be consensus on that. I don't think I've ever seen a useful sparse locking report, so yeah, no tears shed on removing it.
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