cmpxchg.h 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /*
  2. * Generic UP xchg and cmpxchg using interrupt disablement. Does not
  3. * support SMP.
  4. */
  5. #ifndef __ASM_GENERIC_CMPXCHG_H
  6. #define __ASM_GENERIC_CMPXCHG_H
  7. #ifdef CONFIG_SMP
  8. #error "Cannot use generic cmpxchg on SMP"
  9. #endif
  10. #include <linux/irqflags.h>
  11. #ifndef xchg
  12. /*
  13. * This function doesn't exist, so you'll get a linker error if
  14. * something tries to do an invalidly-sized xchg().
  15. */
  16. extern void __xchg_called_with_bad_pointer(void);
  17. static inline
  18. unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
  19. {
  20. unsigned long ret, flags;
  21. switch (size) {
  22. case 1:
  23. #ifdef __xchg_u8
  24. return __xchg_u8(x, ptr);
  25. #else
  26. local_irq_save(flags);
  27. ret = *(volatile u8 *)ptr;
  28. *(volatile u8 *)ptr = x;
  29. local_irq_restore(flags);
  30. return ret;
  31. #endif /* __xchg_u8 */
  32. case 2:
  33. #ifdef __xchg_u16
  34. return __xchg_u16(x, ptr);
  35. #else
  36. local_irq_save(flags);
  37. ret = *(volatile u16 *)ptr;
  38. *(volatile u16 *)ptr = x;
  39. local_irq_restore(flags);
  40. return ret;
  41. #endif /* __xchg_u16 */
  42. case 4:
  43. #ifdef __xchg_u32
  44. return __xchg_u32(x, ptr);
  45. #else
  46. local_irq_save(flags);
  47. ret = *(volatile u32 *)ptr;
  48. *(volatile u32 *)ptr = x;
  49. local_irq_restore(flags);
  50. return ret;
  51. #endif /* __xchg_u32 */
  52. #ifdef CONFIG_64BIT
  53. case 8:
  54. #ifdef __xchg_u64
  55. return __xchg_u64(x, ptr);
  56. #else
  57. local_irq_save(flags);
  58. ret = *(volatile u64 *)ptr;
  59. *(volatile u64 *)ptr = x;
  60. local_irq_restore(flags);
  61. return ret;
  62. #endif /* __xchg_u64 */
  63. #endif /* CONFIG_64BIT */
  64. default:
  65. __xchg_called_with_bad_pointer();
  66. return x;
  67. }
  68. }
  69. #define xchg(ptr, x) \
  70. ((__typeof__(*(ptr))) __xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
  71. #endif /* xchg */
  72. /*
  73. * Atomic compare and exchange.
  74. *
  75. * Do not define __HAVE_ARCH_CMPXCHG because we want to use it to check whether
  76. * a cmpxchg primitive faster than repeated local irq save/restore exists.
  77. */
  78. #include <asm-generic/cmpxchg-local.h>
  79. #define cmpxchg(ptr, o, n) cmpxchg_local((ptr), (o), (n))
  80. #define cmpxchg64(ptr, o, n) cmpxchg64_local((ptr), (o), (n))
  81. #endif /* __ASM_GENERIC_CMPXCHG_H */