linux/include/linux/bit_spinlock.h
<<
>>
Prefs
   1#ifndef __LINUX_BIT_SPINLOCK_H
   2#define __LINUX_BIT_SPINLOCK_H
   3
   4/*
   5 *  bit-based spin_lock()
   6 *
   7 * Don't use this unless you really need to: spin_lock() and spin_unlock()
   8 * are significantly faster.
   9 */
  10static inline void bit_spin_lock(int bitnum, unsigned long *addr)
  11{
  12        /*
  13         * Assuming the lock is uncontended, this never enters
  14         * the body of the outer loop. If it is contended, then
  15         * within the inner loop a non-atomic test is used to
  16         * busywait with less bus contention for a good time to
  17         * attempt to acquire the lock bit.
  18         */
  19        preempt_disable();
  20#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
  21        while (unlikely(test_and_set_bit_lock(bitnum, addr))) {
  22                while (test_bit(bitnum, addr)) {
  23                        preempt_enable();
  24                        cpu_relax();
  25                        preempt_disable();
  26                }
  27        }
  28#endif
  29        __acquire(bitlock);
  30}
  31
  32/*
  33 * Return true if it was acquired
  34 */
  35static inline int bit_spin_trylock(int bitnum, unsigned long *addr)
  36{
  37        preempt_disable();
  38#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
  39        if (unlikely(test_and_set_bit_lock(bitnum, addr))) {
  40                preempt_enable();
  41                return 0;
  42        }
  43#endif
  44        __acquire(bitlock);
  45        return 1;
  46}
  47
  48/*
  49 *  bit-based spin_unlock()
  50 */
  51static inline void bit_spin_unlock(int bitnum, unsigned long *addr)
  52{
  53#ifdef CONFIG_DEBUG_SPINLOCK
  54        BUG_ON(!test_bit(bitnum, addr));
  55#endif
  56#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
  57        clear_bit_unlock(bitnum, addr);
  58#endif
  59        preempt_enable();
  60        __release(bitlock);
  61}
  62
  63/*
  64 *  bit-based spin_unlock()
  65 *  non-atomic version, which can be used eg. if the bit lock itself is
  66 *  protecting the rest of the flags in the word.
  67 */
  68static inline void __bit_spin_unlock(int bitnum, unsigned long *addr)
  69{
  70#ifdef CONFIG_DEBUG_SPINLOCK
  71        BUG_ON(!test_bit(bitnum, addr));
  72#endif
  73#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
  74        __clear_bit_unlock(bitnum, addr);
  75#endif
  76        preempt_enable();
  77        __release(bitlock);
  78}
  79
  80/*
  81 * Return true if the lock is held.
  82 */
  83static inline int bit_spin_is_locked(int bitnum, unsigned long *addr)
  84{
  85#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
  86        return test_bit(bitnum, addr);
  87#elif defined CONFIG_PREEMPT
  88        return preempt_count();
  89#else
  90        return 1;
  91#endif
  92}
  93
  94#endif /* __LINUX_BIT_SPINLOCK_H */
  95
  96