cmpxchg.h 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef __ASM_SH_CMPXCHG_H
  3. #define __ASM_SH_CMPXCHG_H
  4. /*
  5. * Atomic operations that C can't guarantee us. Useful for
  6. * resource counting etc..
  7. */
  8. #include <linux/compiler.h>
  9. #include <linux/types.h>
  10. #if defined(CONFIG_GUSA_RB)
  11. #include <asm/cmpxchg-grb.h>
  12. #elif defined(CONFIG_CPU_SH4A)
  13. #include <asm/cmpxchg-llsc.h>
  14. #elif defined(CONFIG_CPU_J2) && defined(CONFIG_SMP)
  15. #include <asm/cmpxchg-cas.h>
  16. #else
  17. #include <asm/cmpxchg-irq.h>
  18. #endif
  19. extern void __xchg_called_with_bad_pointer(void);
  20. #define __xchg(ptr, x, size) \
  21. ({ \
  22. unsigned long __xchg__res; \
  23. volatile void *__xchg_ptr = (ptr); \
  24. switch (size) { \
  25. case 4: \
  26. __xchg__res = xchg_u32(__xchg_ptr, x); \
  27. break; \
  28. case 2: \
  29. __xchg__res = xchg_u16(__xchg_ptr, x); \
  30. break; \
  31. case 1: \
  32. __xchg__res = xchg_u8(__xchg_ptr, x); \
  33. break; \
  34. default: \
  35. __xchg_called_with_bad_pointer(); \
  36. __xchg__res = x; \
  37. break; \
  38. } \
  39. \
  40. __xchg__res; \
  41. })
  42. #define xchg(ptr,x) \
  43. ((__typeof__(*(ptr)))__xchg((ptr),(unsigned long)(x), sizeof(*(ptr))))
  44. /* This function doesn't exist, so you'll get a linker error
  45. * if something tries to do an invalid cmpxchg(). */
  46. extern void __cmpxchg_called_with_bad_pointer(void);
  47. static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
  48. unsigned long new, int size)
  49. {
  50. switch (size) {
  51. case 4:
  52. return __cmpxchg_u32(ptr, old, new);
  53. }
  54. __cmpxchg_called_with_bad_pointer();
  55. return old;
  56. }
  57. #define cmpxchg(ptr,o,n) \
  58. ({ \
  59. __typeof__(*(ptr)) _o_ = (o); \
  60. __typeof__(*(ptr)) _n_ = (n); \
  61. (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \
  62. (unsigned long)_n_, sizeof(*(ptr))); \
  63. })
  64. #endif /* __ASM_SH_CMPXCHG_H */