[RFC][PATCH 1/4] compiler-context-analysys: Add __cond_releases()

Peter Zijlstra posted 4 patches 2 weeks, 4 days ago
[RFC][PATCH 1/4] compiler-context-analysys: Add __cond_releases()
Posted by Peter Zijlstra 2 weeks, 4 days ago
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
Re: [RFC][PATCH 1/4] compiler-context-analysys: Add __cond_releases()
Posted by Bart Van Assche 2 weeks, 4 days ago
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.
Re: [RFC][PATCH 1/4] compiler-context-analysys: Add __cond_releases()
Posted by Marco Elver 2 weeks, 4 days ago
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.
Re: [RFC][PATCH 1/4] compiler-context-analysys: Add __cond_releases()
Posted by Peter Zijlstra 2 weeks, 4 days ago
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.
Re: [RFC][PATCH 1/4] compiler-context-analysys: Add __cond_releases()
Posted by Bart Van Assche 2 weeks, 4 days ago
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.
Re: [RFC][PATCH 1/4] compiler-context-analysys: Add __cond_releases()
Posted by Marco Elver 2 weeks, 4 days ago
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
>
>