Re: [PATCH RFC 02/24] compiler-capability-analysis: Rename __cond_lock() to __cond_acquire()

From: Peter Zijlstra
Date: Fri Feb 07 2025 - 04:42:02 EST


On Fri, Feb 07, 2025 at 10:32:25AM +0100, Marco Elver wrote:
> On Fri, Feb 07, 2025 at 09:28AM +0100, Peter Zijlstra wrote:
> > On Thu, Feb 06, 2025 at 07:09:56PM +0100, Marco Elver wrote:
> > > Just like the pairing of attribute __acquires() with a matching
> > > function-like macro __acquire(), the attribute __cond_acquires() should
> > > have a matching function-like macro __cond_acquire().
> > >
> > > To be consistent, rename __cond_lock() to __cond_acquire().
> >
> > So I hate this __cond_lock() thing we have with a passion. I think it is
> > one of the very worst annotations possible since it makes a trainwreck
> > of the trylock code.
> >
> > It is a major reason why mutex is not annotated with this nonsense.
> >
> > Also, I think very dim of sparse in general -- I don't think I've ever
> > managed to get a useful warning from between all the noise it generates.
>
> Happy to reduce the use of __cond_lock(). :-)
> Though one problem I found is it's still needed for those complex
> statement-expression *_trylock that spinlock.h/rwlock.h has, where we
> e.g. have (with my changes):
>
> #define raw_spin_trylock_irqsave(lock, flags) \
> __cond_acquire(lock, ({ \
> local_irq_save(flags); \
> _raw_spin_trylock(lock) ? \
> 1 : ({ local_irq_restore(flags); 0; }); \
> }))
>
> Because there's an inner condition using _raw_spin_trylock() and the
> result of _raw_spin_trylock() is no longer directly used in a branch
> that also does the unlock, Clang becomes unhappy and complains. I.e.
> annotating _raw_spin_trylock with __cond_acquires(1, lock) doesn't work
> for this case because it's in a complex statement-expression. The only
> way to make it work was to wrap it into a function that has attribute
> __cond_acquires(1, lock) which is what I made __cond_lock/acquire do.

Does something like:

static inline bool
_raw_spin_trylock_irqsave(raw_spinlock_t *lock, unsigned long *flags)
__cond_acquire(1, lock)
{
local_irq_save(*flags);
if (_raw_spin_trylock(lock))
return true;
local_irq_restore(*flags);
return false;
}

#define raw_spin_trylock_irqsave(lock, flags) \
_raw_spin_trylock_irqsave((lock), &(flags))

work?