atomic.h 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. /*
  2. * Hacked atomics with hpa-specific lw.l/sw.u instructions
  3. */
  4. #ifndef ATOMIC_H
  5. #define ATOMIC_H
  6. #include "compiler.h"
  7. typedef uint32_t atomic_t;
  8. #define lw_l(x) ({ \
  9. volatile atomic_t *__p = (volatile atomic_t *)(x); \
  10. atomic_t __v; \
  11. asm inline volatile("lw.l %0,%1" \
  12. : "=r" (__v), "+m" (*__p) \
  13. : : "memory"); \
  14. (typeof(*(x))) __v; \
  15. })
  16. static inline void _sw_u(volatile atomic_t *__p, atomic_t __v)
  17. {
  18. asm inline volatile("sw.u %1,%0"
  19. : "+m" (*__p) : "r" (__v)
  20. : "memory");
  21. }
  22. #define sw_u(x,v) _sw_u((volatile atomic_t *)(x), (v))
  23. /* Simple barrier-enforcing accessors */
  24. static inline atomic_t atomic_get(const volatile atomic_t *_p)
  25. {
  26. atomic_t _v;
  27. asm inline volatile("lw %0,%1" : "=r" (_v) : "m" (*_p) : "memory");
  28. return _v;
  29. }
  30. static inline void atomic_set(volatile atomic_t *_p, atomic_t _v)
  31. {
  32. asm inline volatile("sw %1,%0" : "=m" (*_p) : "r" (_v) : "memory");
  33. }
  34. static inline atomic_t atomic_swap(volatile atomic_t *_p, atomic_t _v)
  35. {
  36. atomic_t _o = lw_l(_p);
  37. sw_u(_p, _v);
  38. return _o;
  39. }
  40. /* These functions all do read-modify-write returning the old or new values */
  41. #define ATOMIC_OP2_RET(name, op, ret) \
  42. static inline atomic_t \
  43. atomic_ ## name (volatile atomic_t *_p, atomic_t _v) \
  44. { \
  45. atomic_t _o = lw_l(_p); \
  46. atomic_t _n = _o op _v; \
  47. sw_u(_p, _n); \
  48. return ret; \
  49. }
  50. #define ATOMIC_OP2(name, op) \
  51. ATOMIC_OP2_RET(name, op, _n) \
  52. ATOMIC_OP2_RET(xchg_ ## name, op, _o)
  53. ATOMIC_OP2(add, +)
  54. ATOMIC_OP2(sub, -)
  55. ATOMIC_OP2(and, &)
  56. ATOMIC_OP2(or, |)
  57. ATOMIC_OP2(xor, ^)
  58. static inline atomic_t atomic_xchg_and_xor(volatile atomic_t *_p, atomic_t _va, atomic_t _vx)
  59. {
  60. atomic_t _o = lw_l(_p);
  61. atomic_t _n = (_o & _va) ^ _vx;
  62. sw_u(_p, _n);
  63. return _o;
  64. }
  65. #endif /* ATOMIC_H */