Useful for things like unlock fastpaths, which on success release the
lock.
Suggested-by: Marco Elver <elver@google.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
include/linux/compiler-context-analysis.h | 32 ++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
--- a/include/linux/compiler-context-analysis.h
+++ b/include/linux/compiler-context-analysis.h
@@ -320,6 +320,38 @@ static inline void _context_unsafe_alias
*/
#define __releases(...) __releases_ctx_lock(__VA_ARGS__)
+/*
+ * Clang's analysis does not care precisely about the value, only that it is
+ * either zero or non-zero. So the __cond_acquires() interface might be
+ * misleading if we say that @ret is the value returned if acquired. Instead,
+ * provide symbolic variants which we translate.
+ */
+#define __cond_acquires_impl_not_true(x, ...) __try_acquires##__VA_ARGS__##_ctx_lock(0, x)
+#define __cond_acquires_impl_not_false(x, ...) __try_acquires##__VA_ARGS__##_ctx_lock(1, x)
+#define __cond_acquires_impl_not_nonzero(x, ...) __try_acquires##__VA_ARGS__##_ctx_lock(0, x)
+#define __cond_acquires_impl_not_0(x, ...) __try_acquires##__VA_ARGS__##_ctx_lock(1, x)
+#define __cond_acquires_impl_not_nonnull(x, ...) __try_acquires##__VA_ARGS__##_ctx_lock(0, x)
+#define __cond_acquires_impl_not_NULL(x, ...) __try_acquires##__VA_ARGS__##_ctx_lock(1, x)
+
+/**
+ * __cond_releases() - function attribute, function conditionally
+ * releases a context lock exclusively
+ * @ret: abstract value returned by function if context lock releases
+ * @x: context lock instance pointer
+ *
+ * Function attribute declaring that the function conditionally releases the
+ * given context lock instance @x exclusively. The associated context(s) must
+ * be active on entry. The function return value @ret denotes when the context
+ * lock is released.
+ *
+ * @ret may be one of: true, false, nonzero, 0, nonnull, NULL.
+ *
+ * NOTE: clang does not have a native attribute for this; instead implement
+ * it as an unconditional release and a conditional acquire for the
+ * inverted condition -- which is semantically equivalent.
+ */
+#define __cond_releases(ret, x) __releases(x) __cond_acquires_impl_not_##ret(x)
+
/**
* __acquire() - function to acquire context lock exclusively
* @x: context lock instance pointer
On 1/21/26 3:07 AM, Peter Zijlstra wrote: > +#define __cond_releases(ret, x) __releases(x) __cond_acquires_impl_not_##ret(x) Since we have __cond_acquires() and __cond_acquires_shared(), how about also adding a __cond_releases_shared() macro? Thanks, Bart.
On Wed, 21 Jan 2026 at 18:55, Bart Van Assche <bvanassche@acm.org> wrote: > > On 1/21/26 3:07 AM, Peter Zijlstra wrote: > > +#define __cond_releases(ret, x) __releases(x) __cond_acquires_impl_not_##ret(x) > > Since we have __cond_acquires() and __cond_acquires_shared(), how about > also adding a __cond_releases_shared() macro? Since I'm a fan of less code, another option is to introduce it when needed. It's unlikely to be needed, and until then I'd prefer fewer lines of code to be included and maintained. Up to you.
On Wed, Jan 21, 2026 at 07:35:14PM +0100, Marco Elver wrote: > On Wed, 21 Jan 2026 at 18:55, Bart Van Assche <bvanassche@acm.org> wrote: > > > > On 1/21/26 3:07 AM, Peter Zijlstra wrote: > > > +#define __cond_releases(ret, x) __releases(x) __cond_acquires_impl_not_##ret(x) > > > > Since we have __cond_acquires() and __cond_acquires_shared(), how about > > also adding a __cond_releases_shared() macro? > > Since I'm a fan of less code, another option is to introduce it when > needed. It's unlikely to be needed, and until then I'd prefer fewer > lines of code to be included and maintained. Up to you. Right, this was an on-demand thing. Lets add it when it becomes needed.
On 1/21/26 11:02 AM, Peter Zijlstra wrote: > Right, this was an on-demand thing. Lets add it when it becomes needed. Please take a look at vma_start_read() in mm/mmap_lock.c. I think that it needs a __cond_shared_release() annotation. From the documentation block above that function: * IMPORTANT: RCU lock must be held upon entering the function, but upon error * IT IS RELEASED. The caller must handle this correctly. Thanks, Bart.
On Wed, 21 Jan 2026 at 12:13, Peter Zijlstra <peterz@infradead.org> wrote: > > Useful for things like unlock fastpaths, which on success release the > lock. > > Suggested-by: Marco Elver <elver@google.com> > Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Reviewed-by: Marco Elver <elver@google.com> > --- > include/linux/compiler-context-analysis.h | 32 ++++++++++++++++++++++++++++++ > 1 file changed, 32 insertions(+) > > --- a/include/linux/compiler-context-analysis.h > +++ b/include/linux/compiler-context-analysis.h > @@ -320,6 +320,38 @@ static inline void _context_unsafe_alias > */ > #define __releases(...) __releases_ctx_lock(__VA_ARGS__) > > +/* > + * Clang's analysis does not care precisely about the value, only that it is > + * either zero or non-zero. So the __cond_acquires() interface might be > + * misleading if we say that @ret is the value returned if acquired. Instead, > + * provide symbolic variants which we translate. > + */ > +#define __cond_acquires_impl_not_true(x, ...) __try_acquires##__VA_ARGS__##_ctx_lock(0, x) > +#define __cond_acquires_impl_not_false(x, ...) __try_acquires##__VA_ARGS__##_ctx_lock(1, x) > +#define __cond_acquires_impl_not_nonzero(x, ...) __try_acquires##__VA_ARGS__##_ctx_lock(0, x) > +#define __cond_acquires_impl_not_0(x, ...) __try_acquires##__VA_ARGS__##_ctx_lock(1, x) > +#define __cond_acquires_impl_not_nonnull(x, ...) __try_acquires##__VA_ARGS__##_ctx_lock(0, x) > +#define __cond_acquires_impl_not_NULL(x, ...) __try_acquires##__VA_ARGS__##_ctx_lock(1, x) > + > +/** > + * __cond_releases() - function attribute, function conditionally > + * releases a context lock exclusively > + * @ret: abstract value returned by function if context lock releases > + * @x: context lock instance pointer > + * > + * Function attribute declaring that the function conditionally releases the > + * given context lock instance @x exclusively. The associated context(s) must > + * be active on entry. The function return value @ret denotes when the context > + * lock is released. > + * > + * @ret may be one of: true, false, nonzero, 0, nonnull, NULL. > + * > + * NOTE: clang does not have a native attribute for this; instead implement > + * it as an unconditional release and a conditional acquire for the > + * inverted condition -- which is semantically equivalent. > + */ > +#define __cond_releases(ret, x) __releases(x) __cond_acquires_impl_not_##ret(x) > + > /** > * __acquire() - function to acquire context lock exclusively > * @x: context lock instance pointer > >
© 2016 - 2026 Red Hat, Inc.