bit_spinlock.h 2.2 KB

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