From: Marco Elver <elver@google.com>
To: elver@google.com, Peter Zijlstra <peterz@infradead.org>,
Boqun Feng <boqun.feng@gmail.com>,
Ingo Molnar <mingo@kernel.org>, Will Deacon <will@kernel.org>
Cc: "David S. Miller" <davem@davemloft.net>,
Luc Van Oostenryck <luc.vanoostenryck@gmail.com>,
"Paul E. McKenney" <paulmck@kernel.org>,
Alexander Potapenko <glider@google.com>,
Arnd Bergmann <arnd@arndb.de>,
Bart Van Assche <bvanassche@acm.org>,
Bill Wendling <morbo@google.com>, Christoph Hellwig <hch@lst.de>,
Dmitry Vyukov <dvyukov@google.com>,
Eric Dumazet <edumazet@google.com>,
Frederic Weisbecker <frederic@kernel.org>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Herbert Xu <herbert@gondor.apana.org.au>,
Ian Rogers <irogers@google.com>, Jann Horn <jannh@google.com>,
Joel Fernandes <joelagnelf@nvidia.com>,
Jonathan Corbet <corbet@lwn.net>,
Josh Triplett <josh@joshtriplett.org>,
Justin Stitt <justinstitt@google.com>,
Kees Cook <kees@kernel.org>,
Kentaro Takeda <takedakn@nttdata.co.jp>,
Lukas Bulwahn <lukas.bulwahn@gmail.com>,
Mark Rutland <mark.rutland@arm.com>,
Mathieu Desnoyers <mathieu.desnoyers@efficios.com>,
Miguel Ojeda <ojeda@kernel.org>,
Nathan Chancellor <nathan@kernel.org>,
Neeraj Upadhyay <neeraj.upadhyay@kernel.org>,
Nick Desaulniers <nick.desaulniers+lkml@gmail.com>,
Steven Rostedt <rostedt@goodmis.org>,
Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>,
Thomas Gleixner <tglx@linutronix.de>,
Thomas Graf <tgraf@suug.ch>, Uladzislau Rezki <urezki@gmail.com>,
Waiman Long <longman@redhat.com>,
kasan-dev@googlegroups.com, linux-crypto@vger.kernel.org,
linux-doc@vger.kernel.org, linux-kbuild@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-mm@kvack.org,
linux-security-module@vger.kernel.org,
linux-sparse@vger.kernel.org, llvm@lists.linux.dev,
rcu@vger.kernel.org
Subject: [PATCH v3 09/35] compiler-capability-analysis: Change __cond_acquires to take return value
Date: Thu, 18 Sep 2025 15:59:20 +0200 [thread overview]
Message-ID: <20250918140451.1289454-10-elver@google.com> (raw)
In-Reply-To: <20250918140451.1289454-1-elver@google.com>
While Sparse is oblivious to the return value of conditional acquire
functions, Clang's capability analysis needs to know the return value
which indicates successful acquisition.
Add the additional argument, and convert existing uses.
Notably, Clang's interpretation of the value merely relates to the use
in a later conditional branch, i.e. 1 ==> capability acquired in branch
taken if condition non-zero, and 0 ==> capability acquired in branch
taken if condition is zero. Given the precise value does not matter,
introduce symbolic variants to use instead of either 0 or 1, which
should be more intuitive.
No functional change intended.
Signed-off-by: Marco Elver <elver@google.com>
---
v2:
* Use symbolic values for __cond_acquires() and __cond_acquires_shared()
(suggested by Bart).
---
fs/dlm/lock.c | 2 +-
include/linux/compiler-capability-analysis.h | 31 ++++++++++++++++----
include/linux/refcount.h | 6 ++--
include/linux/spinlock.h | 6 ++--
include/linux/spinlock_api_smp.h | 8 ++---
net/ipv4/tcp_sigpool.c | 2 +-
6 files changed, 38 insertions(+), 17 deletions(-)
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
index 6dd3a524cd35..006eb284c8a7 100644
--- a/fs/dlm/lock.c
+++ b/fs/dlm/lock.c
@@ -343,7 +343,7 @@ void dlm_hold_rsb(struct dlm_rsb *r)
/* TODO move this to lib/refcount.c */
static __must_check bool
dlm_refcount_dec_and_write_lock_bh(refcount_t *r, rwlock_t *lock)
-__cond_acquires(lock)
+ __cond_acquires(true, lock)
{
if (refcount_dec_not_one(r))
return false;
diff --git a/include/linux/compiler-capability-analysis.h b/include/linux/compiler-capability-analysis.h
index 6f3f185478bc..ccd312dbbf06 100644
--- a/include/linux/compiler-capability-analysis.h
+++ b/include/linux/compiler-capability-analysis.h
@@ -257,7 +257,7 @@ static inline void _capability_unsafe_alias(void **p) { }
# define __must_hold(x) __attribute__((context(x,1,1)))
# define __must_not_hold(x)
# define __acquires(x) __attribute__((context(x,0,1)))
-# define __cond_acquires(x) __attribute__((context(x,0,-1)))
+# define __cond_acquires(ret, 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)
@@ -300,15 +300,32 @@ static inline void _capability_unsafe_alias(void **p) { }
*/
# define __acquires(x) __acquires_cap(x)
+/*
+ * 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_true(x, ...) __try_acquires##__VA_ARGS__##_cap(1, x)
+#define __cond_acquires_impl_false(x, ...) __try_acquires##__VA_ARGS__##_cap(0, x)
+#define __cond_acquires_impl_nonzero(x, ...) __try_acquires##__VA_ARGS__##_cap(1, x)
+#define __cond_acquires_impl_0(x, ...) __try_acquires##__VA_ARGS__##_cap(0, x)
+#define __cond_acquires_impl_nonnull(x, ...) __try_acquires##__VA_ARGS__##_cap(1, x)
+#define __cond_acquires_impl_NULL(x, ...) __try_acquires##__VA_ARGS__##_cap(0, x)
+
/**
* __cond_acquires() - function attribute, function conditionally
* acquires a capability exclusively
+ * @ret: abstract value returned by function if capability acquired
* @x: capability instance pointer
*
* Function attribute declaring that the function conditionally acquires the
- * given capability instance @x exclusively, but does not release it.
+ * given capability instance @x exclusively, but does not release it. The
+ * function return value @ret denotes when the capability is acquired.
+ *
+ * @ret may be one of: true, false, nonzero, 0, nonnull, NULL.
*/
-# define __cond_acquires(x) __try_acquires_cap(1, x)
+# define __cond_acquires(ret, x) __cond_acquires_impl_##ret(x)
/**
* __releases() - function attribute, function releases a capability exclusively
@@ -375,12 +392,16 @@ static inline void _capability_unsafe_alias(void **p) { }
/**
* __cond_acquires_shared() - function attribute, function conditionally
* acquires a capability shared
+ * @ret: abstract value returned by function if capability acquired
* @x: capability instance pointer
*
* Function attribute declaring that the function conditionally acquires the
- * given capability instance @x with shared access, but does not release it.
+ * given capability instance @x with shared access, but does not release it. The
+ * function return value @ret denotes when the capability is acquired.
+ *
+ * @ret may be one of: true, false, nonzero, 0, nonnull, NULL.
*/
-# define __cond_acquires_shared(x) __try_acquires_shared_cap(1, x)
+# define __cond_acquires_shared(ret, x) __cond_acquires_impl_##ret(x, _shared)
/**
* __releases_shared() - function attribute, function releases a
diff --git a/include/linux/refcount.h b/include/linux/refcount.h
index 80dc023ac2bf..3da377ffb0c2 100644
--- a/include/linux/refcount.h
+++ b/include/linux/refcount.h
@@ -478,9 +478,9 @@ static inline void refcount_dec(refcount_t *r)
extern __must_check bool refcount_dec_if_one(refcount_t *r);
extern __must_check bool refcount_dec_not_one(refcount_t *r);
-extern __must_check bool refcount_dec_and_mutex_lock(refcount_t *r, struct mutex *lock) __cond_acquires(lock);
-extern __must_check bool refcount_dec_and_lock(refcount_t *r, spinlock_t *lock) __cond_acquires(lock);
+extern __must_check bool refcount_dec_and_mutex_lock(refcount_t *r, struct mutex *lock) __cond_acquires(true, lock);
+extern __must_check bool refcount_dec_and_lock(refcount_t *r, spinlock_t *lock) __cond_acquires(true, lock);
extern __must_check bool refcount_dec_and_lock_irqsave(refcount_t *r,
spinlock_t *lock,
- unsigned long *flags) __cond_acquires(lock);
+ unsigned long *flags) __cond_acquires(true, lock);
#endif /* _LINUX_REFCOUNT_H */
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
index 7679f39071e9..22295a126c3a 100644
--- a/include/linux/spinlock.h
+++ b/include/linux/spinlock.h
@@ -362,7 +362,7 @@ static __always_inline void spin_lock_bh(spinlock_t *lock)
}
static __always_inline int spin_trylock(spinlock_t *lock)
- __cond_acquires(lock) __no_capability_analysis
+ __cond_acquires(true, lock) __no_capability_analysis
{
return raw_spin_trylock(&lock->rlock);
}
@@ -422,13 +422,13 @@ static __always_inline void spin_unlock_irqrestore(spinlock_t *lock, unsigned lo
}
static __always_inline int spin_trylock_bh(spinlock_t *lock)
- __cond_acquires(lock) __no_capability_analysis
+ __cond_acquires(true, lock) __no_capability_analysis
{
return raw_spin_trylock_bh(&lock->rlock);
}
static __always_inline int spin_trylock_irq(spinlock_t *lock)
- __cond_acquires(lock) __no_capability_analysis
+ __cond_acquires(true, lock) __no_capability_analysis
{
return raw_spin_trylock_irq(&lock->rlock);
}
diff --git a/include/linux/spinlock_api_smp.h b/include/linux/spinlock_api_smp.h
index fab02d8bf0c9..a77b76003ebb 100644
--- a/include/linux/spinlock_api_smp.h
+++ b/include/linux/spinlock_api_smp.h
@@ -34,8 +34,8 @@ unsigned long __lockfunc _raw_spin_lock_irqsave(raw_spinlock_t *lock)
unsigned long __lockfunc
_raw_spin_lock_irqsave_nested(raw_spinlock_t *lock, int subclass)
__acquires(lock);
-int __lockfunc _raw_spin_trylock(raw_spinlock_t *lock) __cond_acquires(lock);
-int __lockfunc _raw_spin_trylock_bh(raw_spinlock_t *lock) __cond_acquires(lock);
+int __lockfunc _raw_spin_trylock(raw_spinlock_t *lock) __cond_acquires(true, lock);
+int __lockfunc _raw_spin_trylock_bh(raw_spinlock_t *lock) __cond_acquires(true, lock);
void __lockfunc _raw_spin_unlock(raw_spinlock_t *lock) __releases(lock);
void __lockfunc _raw_spin_unlock_bh(raw_spinlock_t *lock) __releases(lock);
void __lockfunc _raw_spin_unlock_irq(raw_spinlock_t *lock) __releases(lock);
@@ -84,7 +84,7 @@ _raw_spin_unlock_irqrestore(raw_spinlock_t *lock, unsigned long flags)
#endif
static inline int __raw_spin_trylock(raw_spinlock_t *lock)
- __cond_acquires(lock)
+ __cond_acquires(true, lock)
{
preempt_disable();
if (do_raw_spin_trylock(lock)) {
@@ -177,7 +177,7 @@ static inline void __raw_spin_unlock_bh(raw_spinlock_t *lock)
}
static inline int __raw_spin_trylock_bh(raw_spinlock_t *lock)
- __cond_acquires(lock)
+ __cond_acquires(true, lock)
{
__local_bh_disable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
if (do_raw_spin_trylock(lock)) {
diff --git a/net/ipv4/tcp_sigpool.c b/net/ipv4/tcp_sigpool.c
index d8a4f192873a..10b2e5970c40 100644
--- a/net/ipv4/tcp_sigpool.c
+++ b/net/ipv4/tcp_sigpool.c
@@ -257,7 +257,7 @@ void tcp_sigpool_get(unsigned int id)
}
EXPORT_SYMBOL_GPL(tcp_sigpool_get);
-int tcp_sigpool_start(unsigned int id, struct tcp_sigpool *c) __cond_acquires(RCU_BH)
+int tcp_sigpool_start(unsigned int id, struct tcp_sigpool *c) __cond_acquires(0, RCU_BH)
{
struct crypto_ahash *hash;
--
2.51.0.384.g4c02a37b29-goog
next prev parent reply other threads:[~2025-09-18 14:05 UTC|newest]
Thread overview: 64+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-18 13:59 [PATCH v3 00/35] Compiler-Based Capability- and Locking-Analysis Marco Elver
2025-09-18 13:59 ` [PATCH v3 01/35] compiler_types: Move lock checking attributes to compiler-capability-analysis.h Marco Elver
2025-09-18 13:59 ` [PATCH v3 02/35] compiler-capability-analysis: Add infrastructure for Clang's capability analysis Marco Elver
2025-09-18 15:58 ` Ian Rogers
2025-09-18 16:03 ` Bart Van Assche
2025-09-18 16:14 ` Steven Rostedt
2025-09-18 13:59 ` [PATCH v3 03/35] compiler-capability-analysis: Add test stub Marco Elver
2025-09-18 13:59 ` [PATCH v3 04/35] Documentation: Add documentation for Compiler-Based Capability Analysis Marco Elver
2025-09-18 13:59 ` [PATCH v3 05/35] checkpatch: Warn about capability_unsafe() without comment Marco Elver
2025-09-18 20:36 ` Joe Perches
2025-09-18 13:59 ` [PATCH v3 06/35] cleanup: Basic compatibility with capability analysis Marco Elver
2025-09-18 13:59 ` [PATCH v3 07/35] lockdep: Annotate lockdep assertions for " Marco Elver
2025-09-18 13:59 ` [PATCH v3 08/35] locking/rwlock, spinlock: Support Clang's " Marco Elver
2025-09-18 13:59 ` Marco Elver [this message]
2025-09-18 13:59 ` [PATCH v3 10/35] locking/mutex: " Marco Elver
2025-09-18 13:59 ` [PATCH v3 11/35] locking/seqlock: " Marco Elver
2025-09-18 13:59 ` [PATCH v3 12/35] bit_spinlock: Include missing <asm/processor.h> Marco Elver
2025-09-18 13:59 ` [PATCH v3 13/35] bit_spinlock: Support Clang's capability analysis Marco Elver
2025-09-18 13:59 ` [PATCH v3 14/35] rcu: " Marco Elver
2025-09-18 13:59 ` [PATCH v3 15/35] srcu: " Marco Elver
2025-09-18 13:59 ` [PATCH v3 16/35] kref: Add capability-analysis annotations Marco Elver
2025-09-18 13:59 ` [PATCH v3 17/35] locking/rwsem: Support Clang's capability analysis Marco Elver
2025-09-18 13:59 ` [PATCH v3 18/35] locking/local_lock: Include missing headers Marco Elver
2025-09-18 13:59 ` [PATCH v3 19/35] locking/local_lock: Support Clang's capability analysis Marco Elver
2025-09-18 13:59 ` [PATCH v3 20/35] locking/ww_mutex: " Marco Elver
2025-09-18 13:59 ` [PATCH v3 21/35] debugfs: Make debugfs_cancellation a capability struct Marco Elver
2025-09-18 13:59 ` [PATCH v3 22/35] compiler-capability-analysis: Remove Sparse support Marco Elver
2025-09-18 13:59 ` [PATCH v3 23/35] compiler-capability-analysis: Remove __cond_lock() function-like helper Marco Elver
2025-09-18 13:59 ` [PATCH v3 24/35] compiler-capability-analysis: Introduce header suppressions Marco Elver
2025-09-18 13:59 ` [PATCH v3 25/35] compiler: Let data_race() imply disabled capability analysis Marco Elver
2025-09-18 13:59 ` [PATCH v3 26/35] MAINTAINERS: Add entry for Capability Analysis Marco Elver
2025-09-18 13:59 ` [PATCH v3 27/35] kfence: Enable capability analysis Marco Elver
2025-09-18 13:59 ` [PATCH v3 28/35] kcov: " Marco Elver
2025-09-18 13:59 ` [PATCH v3 29/35] kcsan: " Marco Elver
2025-09-18 13:59 ` [PATCH v3 30/35] stackdepot: " Marco Elver
2025-09-18 13:59 ` [PATCH v3 31/35] rhashtable: " Marco Elver
2025-09-18 13:59 ` [PATCH v3 32/35] printk: Move locking annotation to printk.c Marco Elver
2025-09-18 13:59 ` [PATCH v3 33/35] security/tomoyo: Enable capability analysis Marco Elver
2025-09-18 13:59 ` [PATCH v3 34/35] crypto: " Marco Elver
2025-09-18 13:59 ` [PATCH v3 35/35] sched: Enable capability analysis for core.c and fair.c Marco Elver
2025-09-18 14:15 ` [PATCH v3 00/35] Compiler-Based Capability- and Locking-Analysis Christoph Hellwig
2025-09-18 14:30 ` Marco Elver
2025-09-18 14:38 ` Christoph Hellwig
2025-09-18 17:45 ` Nathan Chancellor
2025-09-18 19:40 ` Nathan Chancellor
2025-09-19 14:08 ` Christoph Hellwig
2025-09-19 14:09 ` Christoph Hellwig
2025-09-22 9:33 ` Marco Elver
2025-09-22 17:11 ` Christoph Hellwig
2025-09-23 19:49 ` Nathan Chancellor
2025-09-19 17:20 ` Bart Van Assche
2025-09-22 17:12 ` Christoph Hellwig
2025-09-20 10:23 ` Marco Elver
2025-09-20 12:44 ` Marco Elver
2025-09-18 15:49 ` Linus Torvalds
2025-09-18 21:26 ` Marco Elver
2025-09-18 21:47 ` Linus Torvalds
2025-09-19 9:10 ` Marco Elver
2025-11-13 14:30 ` Marco Elver
2025-11-14 4:38 ` Nathan Chancellor
2025-11-14 13:22 ` Marco Elver
2025-09-18 16:21 ` Ian Rogers
2025-09-18 19:41 ` [syzbot ci] " syzbot ci
2025-09-19 7:05 ` Marco Elver
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250918140451.1289454-10-elver@google.com \
--to=elver@google.com \
--cc=arnd@arndb.de \
--cc=boqun.feng@gmail.com \
--cc=bvanassche@acm.org \
--cc=corbet@lwn.net \
--cc=davem@davemloft.net \
--cc=dvyukov@google.com \
--cc=edumazet@google.com \
--cc=frederic@kernel.org \
--cc=glider@google.com \
--cc=gregkh@linuxfoundation.org \
--cc=hch@lst.de \
--cc=herbert@gondor.apana.org.au \
--cc=irogers@google.com \
--cc=jannh@google.com \
--cc=joelagnelf@nvidia.com \
--cc=josh@joshtriplett.org \
--cc=justinstitt@google.com \
--cc=kasan-dev@googlegroups.com \
--cc=kees@kernel.org \
--cc=linux-crypto@vger.kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kbuild@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux-security-module@vger.kernel.org \
--cc=linux-sparse@vger.kernel.org \
--cc=llvm@lists.linux.dev \
--cc=longman@redhat.com \
--cc=luc.vanoostenryck@gmail.com \
--cc=lukas.bulwahn@gmail.com \
--cc=mark.rutland@arm.com \
--cc=mathieu.desnoyers@efficios.com \
--cc=mingo@kernel.org \
--cc=morbo@google.com \
--cc=nathan@kernel.org \
--cc=neeraj.upadhyay@kernel.org \
--cc=nick.desaulniers+lkml@gmail.com \
--cc=ojeda@kernel.org \
--cc=paulmck@kernel.org \
--cc=penguin-kernel@I-love.SAKURA.ne.jp \
--cc=peterz@infradead.org \
--cc=rcu@vger.kernel.org \
--cc=rostedt@goodmis.org \
--cc=takedakn@nttdata.co.jp \
--cc=tglx@linutronix.de \
--cc=tgraf@suug.ch \
--cc=urezki@gmail.com \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).