[PATCH RFC 10/24] compiler-capability-analysis: Change __cond_acquires to take return value

From: Marco Elver
Date: Thu Feb 06 2025 - 13:25:02 EST


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.

No functional change intended.

Signed-off-by: Marco Elver <elver@xxxxxxxxxx>
---
fs/dlm/lock.c | 2 +-
include/linux/compiler-capability-analysis.h | 14 +++++++++-----
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, 21 insertions(+), 17 deletions(-)

diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
index c8ff88f1cdcf..e39ca02b793e 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(1, 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 ca63b6513dc3..10c03133ac4d 100644
--- a/include/linux/compiler-capability-analysis.h
+++ b/include/linux/compiler-capability-analysis.h
@@ -231,7 +231,7 @@
# 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)
@@ -277,12 +277,14 @@
/**
* __cond_acquires() - function attribute, function conditionally
* acquires a capability exclusively
+ * @ret: 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.
*/
-# define __cond_acquires(x) __try_acquires_cap(1, x)
+# define __cond_acquires(ret, x) __try_acquires_cap(ret, x)

/**
* __releases() - function attribute, function releases a capability exclusively
@@ -349,12 +351,14 @@
/**
* __cond_acquires_shared() - function attribute, function conditionally
* acquires a capability shared
+ * @ret: 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.
*/
-# define __cond_acquires_shared(x) __try_acquires_shared_cap(1, x)
+# define __cond_acquires_shared(ret, x) __try_acquires_shared_cap(ret, x)

/**
* __releases_shared() - function attribute, function releases a
diff --git a/include/linux/refcount.h b/include/linux/refcount.h
index 35f039ecb272..f63ce3fadfa3 100644
--- a/include/linux/refcount.h
+++ b/include/linux/refcount.h
@@ -353,9 +353,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(1, lock);
+extern __must_check bool refcount_dec_and_lock(refcount_t *r, spinlock_t *lock) __cond_acquires(1, 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(1, lock);
#endif /* _LINUX_REFCOUNT_H */
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
index 1646a9920fd7..de5118d0e718 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(1, lock) __no_capability_analysis
{
return raw_spin_trylock(&lock->rlock);
}
@@ -420,13 +420,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(1, 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(1, 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..9b6f7a5a0705 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(1, lock);
+int __lockfunc _raw_spin_trylock_bh(raw_spinlock_t *lock) __cond_acquires(1, 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(1, 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(1, 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.48.1.502.g6dc24dfdaf-goog