instrumented-atomic.h 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * This file provides wrappers with sanitizer instrumentation for atomic bit
  4. * operations.
  5. *
  6. * To use this functionality, an arch's bitops.h file needs to define each of
  7. * the below bit operations with an arch_ prefix (e.g. arch_set_bit(),
  8. * arch___set_bit(), etc.).
  9. */
  10. #ifndef _ASM_GENERIC_BITOPS_INSTRUMENTED_ATOMIC_H
  11. #define _ASM_GENERIC_BITOPS_INSTRUMENTED_ATOMIC_H
  12. #include <linux/instrumented.h>
  13. /**
  14. * set_bit - Atomically set a bit in memory
  15. * @nr: the bit to set
  16. * @addr: the address to start counting from
  17. *
  18. * This is a relaxed atomic operation (no implied memory barriers).
  19. *
  20. * Note that @nr may be almost arbitrarily large; this function is not
  21. * restricted to acting on a single-word quantity.
  22. */
  23. static __always_inline void set_bit(long nr, volatile unsigned long *addr)
  24. {
  25. instrument_atomic_write(addr + BIT_WORD(nr), sizeof(long));
  26. arch_set_bit(nr, addr);
  27. }
  28. /**
  29. * clear_bit - Clears a bit in memory
  30. * @nr: Bit to clear
  31. * @addr: Address to start counting from
  32. *
  33. * This is a relaxed atomic operation (no implied memory barriers).
  34. */
  35. static __always_inline void clear_bit(long nr, volatile unsigned long *addr)
  36. {
  37. instrument_atomic_write(addr + BIT_WORD(nr), sizeof(long));
  38. arch_clear_bit(nr, addr);
  39. }
  40. /**
  41. * change_bit - Toggle a bit in memory
  42. * @nr: Bit to change
  43. * @addr: Address to start counting from
  44. *
  45. * This is a relaxed atomic operation (no implied memory barriers).
  46. *
  47. * Note that @nr may be almost arbitrarily large; this function is not
  48. * restricted to acting on a single-word quantity.
  49. */
  50. static __always_inline void change_bit(long nr, volatile unsigned long *addr)
  51. {
  52. instrument_atomic_write(addr + BIT_WORD(nr), sizeof(long));
  53. arch_change_bit(nr, addr);
  54. }
  55. /**
  56. * test_and_set_bit - Set a bit and return its old value
  57. * @nr: Bit to set
  58. * @addr: Address to count from
  59. *
  60. * This is an atomic fully-ordered operation (implied full memory barrier).
  61. */
  62. static __always_inline bool test_and_set_bit(long nr, volatile unsigned long *addr)
  63. {
  64. kcsan_mb();
  65. instrument_atomic_read_write(addr + BIT_WORD(nr), sizeof(long));
  66. return arch_test_and_set_bit(nr, addr);
  67. }
  68. /**
  69. * test_and_clear_bit - Clear a bit and return its old value
  70. * @nr: Bit to clear
  71. * @addr: Address to count from
  72. *
  73. * This is an atomic fully-ordered operation (implied full memory barrier).
  74. */
  75. static __always_inline bool test_and_clear_bit(long nr, volatile unsigned long *addr)
  76. {
  77. kcsan_mb();
  78. instrument_atomic_read_write(addr + BIT_WORD(nr), sizeof(long));
  79. return arch_test_and_clear_bit(nr, addr);
  80. }
  81. /**
  82. * test_and_change_bit - Change a bit and return its old value
  83. * @nr: Bit to change
  84. * @addr: Address to count from
  85. *
  86. * This is an atomic fully-ordered operation (implied full memory barrier).
  87. */
  88. static __always_inline bool test_and_change_bit(long nr, volatile unsigned long *addr)
  89. {
  90. kcsan_mb();
  91. instrument_atomic_read_write(addr + BIT_WORD(nr), sizeof(long));
  92. return arch_test_and_change_bit(nr, addr);
  93. }
  94. #endif /* _ASM_GENERIC_BITOPS_INSTRUMENTED_NON_ATOMIC_H */