Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <linux/export.h>
0003 #include <linux/spinlock.h>
0004 #include <linux/atomic.h>
0005 
0006 /*
0007  * This is an implementation of the notion of "decrement a
0008  * reference count, and return locked if it decremented to zero".
0009  *
0010  * NOTE NOTE NOTE! This is _not_ equivalent to
0011  *
0012  *  if (atomic_dec_and_test(&atomic)) {
0013  *      spin_lock(&lock);
0014  *      return 1;
0015  *  }
0016  *  return 0;
0017  *
0018  * because the spin-lock and the decrement must be
0019  * "atomic".
0020  */
0021 int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
0022 {
0023     /* Subtract 1 from counter unless that drops it to 0 (ie. it was 1) */
0024     if (atomic_add_unless(atomic, -1, 1))
0025         return 0;
0026 
0027     /* Otherwise do it the slow way */
0028     spin_lock(lock);
0029     if (atomic_dec_and_test(atomic))
0030         return 1;
0031     spin_unlock(lock);
0032     return 0;
0033 }
0034 
0035 EXPORT_SYMBOL(_atomic_dec_and_lock);
0036 
0037 int _atomic_dec_and_lock_irqsave(atomic_t *atomic, spinlock_t *lock,
0038                  unsigned long *flags)
0039 {
0040     /* Subtract 1 from counter unless that drops it to 0 (ie. it was 1) */
0041     if (atomic_add_unless(atomic, -1, 1))
0042         return 0;
0043 
0044     /* Otherwise do it the slow way */
0045     spin_lock_irqsave(lock, *flags);
0046     if (atomic_dec_and_test(atomic))
0047         return 1;
0048     spin_unlock_irqrestore(lock, *flags);
0049     return 0;
0050 }
0051 EXPORT_SYMBOL(_atomic_dec_and_lock_irqsave);