bit_spinlock.h 2.3 KB

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