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