Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

compiler-context-analysis: Change __cond_acquires to take return value

While Sparse is oblivious to the return value of conditional acquire
functions, Clang's context 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 ==> context lock acquired in
branch taken if condition non-zero, and 0 ==> context lock 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>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://patch.msgid.link/20251219154418.3592607-10-elver@google.com

authored by

Marco Elver and committed by
Peter Zijlstra
38f1311a f16a802d

+38 -17
+1 -1
fs/dlm/lock.c
··· 343 343 /* TODO move this to lib/refcount.c */ 344 344 static __must_check bool 345 345 dlm_refcount_dec_and_write_lock_bh(refcount_t *r, rwlock_t *lock) 346 - __cond_acquires(lock) 346 + __cond_acquires(true, lock) 347 347 { 348 348 if (refcount_dec_not_one(r)) 349 349 return false;
+26 -5
include/linux/compiler-context-analysis.h
··· 271 271 # define __must_hold(x) __attribute__((context(x,1,1))) 272 272 # define __must_not_hold(x) 273 273 # define __acquires(x) __attribute__((context(x,0,1))) 274 - # define __cond_acquires(x) __attribute__((context(x,0,-1))) 274 + # define __cond_acquires(ret, x) __attribute__((context(x,0,-1))) 275 275 # define __releases(x) __attribute__((context(x,1,0))) 276 276 # define __acquire(x) __context__(x,1) 277 277 # define __release(x) __context__(x,-1) ··· 314 314 */ 315 315 # define __acquires(x) __acquires_ctx_lock(x) 316 316 317 + /* 318 + * Clang's analysis does not care precisely about the value, only that it is 319 + * either zero or non-zero. So the __cond_acquires() interface might be 320 + * misleading if we say that @ret is the value returned if acquired. Instead, 321 + * provide symbolic variants which we translate. 322 + */ 323 + #define __cond_acquires_impl_true(x, ...) __try_acquires##__VA_ARGS__##_ctx_lock(1, x) 324 + #define __cond_acquires_impl_false(x, ...) __try_acquires##__VA_ARGS__##_ctx_lock(0, x) 325 + #define __cond_acquires_impl_nonzero(x, ...) __try_acquires##__VA_ARGS__##_ctx_lock(1, x) 326 + #define __cond_acquires_impl_0(x, ...) __try_acquires##__VA_ARGS__##_ctx_lock(0, x) 327 + #define __cond_acquires_impl_nonnull(x, ...) __try_acquires##__VA_ARGS__##_ctx_lock(1, x) 328 + #define __cond_acquires_impl_NULL(x, ...) __try_acquires##__VA_ARGS__##_ctx_lock(0, x) 329 + 317 330 /** 318 331 * __cond_acquires() - function attribute, function conditionally 319 332 * acquires a context lock exclusively 333 + * @ret: abstract value returned by function if context lock acquired 320 334 * @x: context lock instance pointer 321 335 * 322 336 * Function attribute declaring that the function conditionally acquires the 323 - * given context lock instance @x exclusively, but does not release it. 337 + * given context lock instance @x exclusively, but does not release it. The 338 + * function return value @ret denotes when the context lock is acquired. 339 + * 340 + * @ret may be one of: true, false, nonzero, 0, nonnull, NULL. 324 341 */ 325 - # define __cond_acquires(x) __try_acquires_ctx_lock(1, x) 342 + # define __cond_acquires(ret, x) __cond_acquires_impl_##ret(x) 326 343 327 344 /** 328 345 * __releases() - function attribute, function releases a context lock exclusively ··· 406 389 /** 407 390 * __cond_acquires_shared() - function attribute, function conditionally 408 391 * acquires a context lock shared 392 + * @ret: abstract value returned by function if context lock acquired 409 393 * @x: context lock instance pointer 410 394 * 411 395 * Function attribute declaring that the function conditionally acquires the 412 - * given context lock instance @x with shared access, but does not release it. 396 + * given context lock instance @x with shared access, but does not release it. The 397 + * function return value @ret denotes when the context lock is acquired. 398 + * 399 + * @ret may be one of: true, false, nonzero, 0, nonnull, NULL. 413 400 */ 414 - # define __cond_acquires_shared(x) __try_acquires_shared_ctx_lock(1, x) 401 + # define __cond_acquires_shared(ret, x) __cond_acquires_impl_##ret(x, _shared) 415 402 416 403 /** 417 404 * __releases_shared() - function attribute, function releases a
+3 -3
include/linux/refcount.h
··· 478 478 479 479 extern __must_check bool refcount_dec_if_one(refcount_t *r); 480 480 extern __must_check bool refcount_dec_not_one(refcount_t *r); 481 - extern __must_check bool refcount_dec_and_mutex_lock(refcount_t *r, struct mutex *lock) __cond_acquires(lock); 482 - extern __must_check bool refcount_dec_and_lock(refcount_t *r, spinlock_t *lock) __cond_acquires(lock); 481 + extern __must_check bool refcount_dec_and_mutex_lock(refcount_t *r, struct mutex *lock) __cond_acquires(true, lock); 482 + extern __must_check bool refcount_dec_and_lock(refcount_t *r, spinlock_t *lock) __cond_acquires(true, lock); 483 483 extern __must_check bool refcount_dec_and_lock_irqsave(refcount_t *r, 484 484 spinlock_t *lock, 485 - unsigned long *flags) __cond_acquires(lock); 485 + unsigned long *flags) __cond_acquires(true, lock); 486 486 #endif /* _LINUX_REFCOUNT_H */
+3 -3
include/linux/spinlock.h
··· 362 362 } 363 363 364 364 static __always_inline int spin_trylock(spinlock_t *lock) 365 - __cond_acquires(lock) __no_context_analysis 365 + __cond_acquires(true, lock) __no_context_analysis 366 366 { 367 367 return raw_spin_trylock(&lock->rlock); 368 368 } ··· 422 422 } 423 423 424 424 static __always_inline int spin_trylock_bh(spinlock_t *lock) 425 - __cond_acquires(lock) __no_context_analysis 425 + __cond_acquires(true, lock) __no_context_analysis 426 426 { 427 427 return raw_spin_trylock_bh(&lock->rlock); 428 428 } 429 429 430 430 static __always_inline int spin_trylock_irq(spinlock_t *lock) 431 - __cond_acquires(lock) __no_context_analysis 431 + __cond_acquires(true, lock) __no_context_analysis 432 432 { 433 433 return raw_spin_trylock_irq(&lock->rlock); 434 434 }
+4 -4
include/linux/spinlock_api_smp.h
··· 34 34 unsigned long __lockfunc 35 35 _raw_spin_lock_irqsave_nested(raw_spinlock_t *lock, int subclass) 36 36 __acquires(lock); 37 - int __lockfunc _raw_spin_trylock(raw_spinlock_t *lock) __cond_acquires(lock); 38 - int __lockfunc _raw_spin_trylock_bh(raw_spinlock_t *lock) __cond_acquires(lock); 37 + int __lockfunc _raw_spin_trylock(raw_spinlock_t *lock) __cond_acquires(true, lock); 38 + int __lockfunc _raw_spin_trylock_bh(raw_spinlock_t *lock) __cond_acquires(true, lock); 39 39 void __lockfunc _raw_spin_unlock(raw_spinlock_t *lock) __releases(lock); 40 40 void __lockfunc _raw_spin_unlock_bh(raw_spinlock_t *lock) __releases(lock); 41 41 void __lockfunc _raw_spin_unlock_irq(raw_spinlock_t *lock) __releases(lock); ··· 84 84 #endif 85 85 86 86 static inline int __raw_spin_trylock(raw_spinlock_t *lock) 87 - __cond_acquires(lock) 87 + __cond_acquires(true, lock) 88 88 { 89 89 preempt_disable(); 90 90 if (do_raw_spin_trylock(lock)) { ··· 177 177 } 178 178 179 179 static inline int __raw_spin_trylock_bh(raw_spinlock_t *lock) 180 - __cond_acquires(lock) 180 + __cond_acquires(true, lock) 181 181 { 182 182 __local_bh_disable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET); 183 183 if (do_raw_spin_trylock(lock)) {
+1 -1
net/ipv4/tcp_sigpool.c
··· 257 257 } 258 258 EXPORT_SYMBOL_GPL(tcp_sigpool_get); 259 259 260 - int tcp_sigpool_start(unsigned int id, struct tcp_sigpool *c) __cond_acquires(RCU_BH) 260 + int tcp_sigpool_start(unsigned int id, struct tcp_sigpool *c) __cond_acquires(0, RCU_BH) 261 261 { 262 262 struct crypto_ahash *hash; 263 263