atomic.h 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef __ARCH_H8300_ATOMIC__
  3. #define __ARCH_H8300_ATOMIC__
  4. #include <linux/compiler.h>
  5. #include <linux/types.h>
  6. #include <asm/cmpxchg.h>
  7. #include <asm/irqflags.h>
  8. /*
  9. * Atomic operations that C can't guarantee us. Useful for
  10. * resource counting etc..
  11. */
  12. #define ATOMIC_INIT(i) { (i) }
  13. #define atomic_read(v) READ_ONCE((v)->counter)
  14. #define atomic_set(v, i) WRITE_ONCE(((v)->counter), (i))
  15. #define ATOMIC_OP_RETURN(op, c_op) \
  16. static inline int atomic_##op##_return(int i, atomic_t *v) \
  17. { \
  18. h8300flags flags; \
  19. int ret; \
  20. \
  21. flags = arch_local_irq_save(); \
  22. ret = v->counter c_op i; \
  23. arch_local_irq_restore(flags); \
  24. return ret; \
  25. }
  26. #define ATOMIC_FETCH_OP(op, c_op) \
  27. static inline int atomic_fetch_##op(int i, atomic_t *v) \
  28. { \
  29. h8300flags flags; \
  30. int ret; \
  31. \
  32. flags = arch_local_irq_save(); \
  33. ret = v->counter; \
  34. v->counter c_op i; \
  35. arch_local_irq_restore(flags); \
  36. return ret; \
  37. }
  38. #define ATOMIC_OP(op, c_op) \
  39. static inline void atomic_##op(int i, atomic_t *v) \
  40. { \
  41. h8300flags flags; \
  42. \
  43. flags = arch_local_irq_save(); \
  44. v->counter c_op i; \
  45. arch_local_irq_restore(flags); \
  46. }
  47. ATOMIC_OP_RETURN(add, +=)
  48. ATOMIC_OP_RETURN(sub, -=)
  49. #define ATOMIC_OPS(op, c_op) \
  50. ATOMIC_OP(op, c_op) \
  51. ATOMIC_FETCH_OP(op, c_op)
  52. ATOMIC_OPS(and, &=)
  53. ATOMIC_OPS(or, |=)
  54. ATOMIC_OPS(xor, ^=)
  55. ATOMIC_OPS(add, +=)
  56. ATOMIC_OPS(sub, -=)
  57. #undef ATOMIC_OPS
  58. #undef ATOMIC_OP_RETURN
  59. #undef ATOMIC_OP
  60. static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
  61. {
  62. int ret;
  63. h8300flags flags;
  64. flags = arch_local_irq_save();
  65. ret = v->counter;
  66. if (likely(ret == old))
  67. v->counter = new;
  68. arch_local_irq_restore(flags);
  69. return ret;
  70. }
  71. static inline int atomic_fetch_add_unless(atomic_t *v, int a, int u)
  72. {
  73. int ret;
  74. h8300flags flags;
  75. flags = arch_local_irq_save();
  76. ret = v->counter;
  77. if (ret != u)
  78. v->counter += a;
  79. arch_local_irq_restore(flags);
  80. return ret;
  81. }
  82. #define atomic_fetch_add_unless atomic_fetch_add_unless
  83. #endif /* __ARCH_H8300_ATOMIC __ */