locking/refcounts: Implement refcount_dec_and_lock_irqsave()
There are in-tree users of refcount_dec_and_lock() which must acquire the spin lock with interrupts disabled. To workaround the lack of an irqsave variant of refcount_dec_and_lock() they use local_irq_save() at the call site. This causes extra code and creates in some places unneeded long interrupt disabled times. These places need also extra treatment for PREEMPT_RT due to the disconnect of the irq disabling and the lock function. Implement the missing irqsave variant of the function. Signed-off-by: Anna-Maria Gleixner <anna-maria@linutronix.de> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://lkml.kernel.org/r20180612161621.22645-4-bigeasy@linutronix.de [bigeasy: s@atomic_dec_and_lock@refcount_dec_and_lock@g]
This commit is contained in:
parent
ccfbb5bed4
commit
7ea959c457
|
@ -98,5 +98,7 @@ 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);
|
||||
extern __must_check bool refcount_dec_and_lock(refcount_t *r, spinlock_t *lock);
|
||||
|
||||
extern __must_check bool refcount_dec_and_lock_irqsave(refcount_t *r,
|
||||
spinlock_t *lock,
|
||||
unsigned long *flags);
|
||||
#endif /* _LINUX_REFCOUNT_H */
|
||||
|
|
|
@ -350,3 +350,31 @@ bool refcount_dec_and_lock(refcount_t *r, spinlock_t *lock)
|
|||
}
|
||||
EXPORT_SYMBOL(refcount_dec_and_lock);
|
||||
|
||||
/**
|
||||
* refcount_dec_and_lock_irqsave - return holding spinlock with disabled
|
||||
* interrupts if able to decrement refcount to 0
|
||||
* @r: the refcount
|
||||
* @lock: the spinlock to be locked
|
||||
* @flags: saved IRQ-flags if the is acquired
|
||||
*
|
||||
* Same as refcount_dec_and_lock() above except that the spinlock is acquired
|
||||
* with disabled interupts.
|
||||
*
|
||||
* Return: true and hold spinlock if able to decrement refcount to 0, false
|
||||
* otherwise
|
||||
*/
|
||||
bool refcount_dec_and_lock_irqsave(refcount_t *r, spinlock_t *lock,
|
||||
unsigned long *flags)
|
||||
{
|
||||
if (refcount_dec_not_one(r))
|
||||
return false;
|
||||
|
||||
spin_lock_irqsave(lock, *flags);
|
||||
if (!refcount_dec_and_test(r)) {
|
||||
spin_unlock_irqrestore(lock, *flags);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(refcount_dec_and_lock_irqsave);
|
||||
|
|
Loading…
Reference in New Issue