sync_bitops.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. #ifndef _ASM_X86_SYNC_BITOPS_H
  2. #define _ASM_X86_SYNC_BITOPS_H
  3. /*
  4. * Copyright 1992, Linus Torvalds.
  5. */
  6. /*
  7. * These have to be done with inline assembly: that way the bit-setting
  8. * is guaranteed to be atomic. All bit operations return 0 if the bit
  9. * was cleared before the operation and != 0 if it was not.
  10. *
  11. * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
  12. */
  13. #define ADDR (*(volatile long *)addr)
  14. /**
  15. * sync_set_bit - Atomically set a bit in memory
  16. * @nr: the bit to set
  17. * @addr: the address to start counting from
  18. *
  19. * This function is atomic and may not be reordered. See __set_bit()
  20. * if you do not require the atomic guarantees.
  21. *
  22. * Note that @nr may be almost arbitrarily large; this function is not
  23. * restricted to acting on a single-word quantity.
  24. */
  25. static inline void sync_set_bit(int nr, volatile unsigned long *addr)
  26. {
  27. asm volatile("lock; btsl %1,%0"
  28. : "+m" (ADDR)
  29. : "Ir" (nr)
  30. : "memory");
  31. }
  32. /**
  33. * sync_clear_bit - Clears a bit in memory
  34. * @nr: Bit to clear
  35. * @addr: Address to start counting from
  36. *
  37. * sync_clear_bit() is atomic and may not be reordered. However, it does
  38. * not contain a memory barrier, so if it is used for locking purposes,
  39. * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
  40. * in order to ensure changes are visible on other processors.
  41. */
  42. static inline void sync_clear_bit(int nr, volatile unsigned long *addr)
  43. {
  44. asm volatile("lock; btrl %1,%0"
  45. : "+m" (ADDR)
  46. : "Ir" (nr)
  47. : "memory");
  48. }
  49. /**
  50. * sync_change_bit - Toggle a bit in memory
  51. * @nr: Bit to change
  52. * @addr: Address to start counting from
  53. *
  54. * sync_change_bit() is atomic and may not be reordered.
  55. * Note that @nr may be almost arbitrarily large; this function is not
  56. * restricted to acting on a single-word quantity.
  57. */
  58. static inline void sync_change_bit(int nr, volatile unsigned long *addr)
  59. {
  60. asm volatile("lock; btcl %1,%0"
  61. : "+m" (ADDR)
  62. : "Ir" (nr)
  63. : "memory");
  64. }
  65. /**
  66. * sync_test_and_set_bit - Set a bit and return its old value
  67. * @nr: Bit to set
  68. * @addr: Address to count from
  69. *
  70. * This operation is atomic and cannot be reordered.
  71. * It also implies a memory barrier.
  72. */
  73. static inline int sync_test_and_set_bit(int nr, volatile unsigned long *addr)
  74. {
  75. int oldbit;
  76. asm volatile("lock; btsl %2,%1\n\tsbbl %0,%0"
  77. : "=r" (oldbit), "+m" (ADDR)
  78. : "Ir" (nr) : "memory");
  79. return oldbit;
  80. }
  81. /**
  82. * sync_test_and_clear_bit - Clear a bit and return its old value
  83. * @nr: Bit to clear
  84. * @addr: Address to count from
  85. *
  86. * This operation is atomic and cannot be reordered.
  87. * It also implies a memory barrier.
  88. */
  89. static inline int sync_test_and_clear_bit(int nr, volatile unsigned long *addr)
  90. {
  91. int oldbit;
  92. asm volatile("lock; btrl %2,%1\n\tsbbl %0,%0"
  93. : "=r" (oldbit), "+m" (ADDR)
  94. : "Ir" (nr) : "memory");
  95. return oldbit;
  96. }
  97. /**
  98. * sync_test_and_change_bit - Change a bit and return its old value
  99. * @nr: Bit to change
  100. * @addr: Address to count from
  101. *
  102. * This operation is atomic and cannot be reordered.
  103. * It also implies a memory barrier.
  104. */
  105. static inline int sync_test_and_change_bit(int nr, volatile unsigned long *addr)
  106. {
  107. int oldbit;
  108. asm volatile("lock; btcl %2,%1\n\tsbbl %0,%0"
  109. : "=r" (oldbit), "+m" (ADDR)
  110. : "Ir" (nr) : "memory");
  111. return oldbit;
  112. }
  113. #define sync_test_bit(nr, addr) test_bit(nr, addr)
  114. #undef ADDR
  115. #endif /* _ASM_X86_SYNC_BITOPS_H */