atomic.h 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef _ASM_GENERIC_BITOPS_ATOMIC_H_
  3. #define _ASM_GENERIC_BITOPS_ATOMIC_H_
  4. #include <linux/atomic.h>
  5. #include <linux/compiler.h>
  6. #include <asm/barrier.h>
  7. /*
  8. * Implementation of atomic bitops using atomic-fetch ops.
  9. * See Documentation/atomic_bitops.txt for details.
  10. */
  11. static inline void set_bit(unsigned int nr, volatile unsigned long *p)
  12. {
  13. p += BIT_WORD(nr);
  14. atomic_long_or(BIT_MASK(nr), (atomic_long_t *)p);
  15. }
  16. static inline void clear_bit(unsigned int nr, volatile unsigned long *p)
  17. {
  18. p += BIT_WORD(nr);
  19. atomic_long_andnot(BIT_MASK(nr), (atomic_long_t *)p);
  20. }
  21. static inline void change_bit(unsigned int nr, volatile unsigned long *p)
  22. {
  23. p += BIT_WORD(nr);
  24. atomic_long_xor(BIT_MASK(nr), (atomic_long_t *)p);
  25. }
  26. static inline int test_and_set_bit(unsigned int nr, volatile unsigned long *p)
  27. {
  28. long old;
  29. unsigned long mask = BIT_MASK(nr);
  30. p += BIT_WORD(nr);
  31. if (READ_ONCE(*p) & mask)
  32. return 1;
  33. old = atomic_long_fetch_or(mask, (atomic_long_t *)p);
  34. return !!(old & mask);
  35. }
  36. static inline int test_and_clear_bit(unsigned int nr, volatile unsigned long *p)
  37. {
  38. long old;
  39. unsigned long mask = BIT_MASK(nr);
  40. p += BIT_WORD(nr);
  41. if (!(READ_ONCE(*p) & mask))
  42. return 0;
  43. old = atomic_long_fetch_andnot(mask, (atomic_long_t *)p);
  44. return !!(old & mask);
  45. }
  46. static inline int test_and_change_bit(unsigned int nr, volatile unsigned long *p)
  47. {
  48. long old;
  49. unsigned long mask = BIT_MASK(nr);
  50. p += BIT_WORD(nr);
  51. old = atomic_long_fetch_xor(mask, (atomic_long_t *)p);
  52. return !!(old & mask);
  53. }
  54. #endif /* _ASM_GENERIC_BITOPS_ATOMIC_H */