aboutsummaryrefslogtreecommitdiffstats
path: root/arch/tile/include/asm/cmpxchg.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/tile/include/asm/cmpxchg.h')
-rw-r--r--arch/tile/include/asm/cmpxchg.h97
1 files changed, 73 insertions, 24 deletions
diff --git a/arch/tile/include/asm/cmpxchg.h b/arch/tile/include/asm/cmpxchg.h
index 1da5bfbd8c61..4001d5eab4bb 100644
--- a/arch/tile/include/asm/cmpxchg.h
+++ b/arch/tile/include/asm/cmpxchg.h
@@ -20,59 +20,108 @@
20 20
21#ifndef __ASSEMBLY__ 21#ifndef __ASSEMBLY__
22 22
23/* Nonexistent functions intended to cause link errors. */ 23#include <asm/barrier.h>
24extern unsigned long __xchg_called_with_bad_pointer(void);
25extern unsigned long __cmpxchg_called_with_bad_pointer(void);
26 24
27#define xchg(ptr, x) \ 25/* Nonexistent functions intended to cause compile errors. */
26extern void __xchg_called_with_bad_pointer(void)
27 __compiletime_error("Bad argument size for xchg");
28extern void __cmpxchg_called_with_bad_pointer(void)
29 __compiletime_error("Bad argument size for cmpxchg");
30
31#ifndef __tilegx__
32
33/* Note the _atomic_xxx() routines include a final mb(). */
34int _atomic_xchg(int *ptr, int n);
35int _atomic_xchg_add(int *v, int i);
36int _atomic_xchg_add_unless(int *v, int a, int u);
37int _atomic_cmpxchg(int *ptr, int o, int n);
38u64 _atomic64_xchg(u64 *v, u64 n);
39u64 _atomic64_xchg_add(u64 *v, u64 i);
40u64 _atomic64_xchg_add_unless(u64 *v, u64 a, u64 u);
41u64 _atomic64_cmpxchg(u64 *v, u64 o, u64 n);
42
43#define xchg(ptr, n) \
44 ({ \
45 if (sizeof(*(ptr)) != 4) \
46 __xchg_called_with_bad_pointer(); \
47 smp_mb(); \
48 (typeof(*(ptr)))_atomic_xchg((int *)(ptr), (int)(n)); \
49 })
50
51#define cmpxchg(ptr, o, n) \
52 ({ \
53 if (sizeof(*(ptr)) != 4) \
54 __cmpxchg_called_with_bad_pointer(); \
55 smp_mb(); \
56 (typeof(*(ptr)))_atomic_cmpxchg((int *)ptr, (int)o, (int)n); \
57 })
58
59#define xchg64(ptr, n) \
60 ({ \
61 if (sizeof(*(ptr)) != 8) \
62 __xchg_called_with_bad_pointer(); \
63 smp_mb(); \
64 (typeof(*(ptr)))_atomic64_xchg((u64 *)(ptr), (u64)(n)); \
65 })
66
67#define cmpxchg64(ptr, o, n) \
68 ({ \
69 if (sizeof(*(ptr)) != 8) \
70 __cmpxchg_called_with_bad_pointer(); \
71 smp_mb(); \
72 (typeof(*(ptr)))_atomic64_cmpxchg((u64 *)ptr, (u64)o, (u64)n); \
73 })
74
75#else
76
77#define xchg(ptr, n) \
28 ({ \ 78 ({ \
29 typeof(*(ptr)) __x; \ 79 typeof(*(ptr)) __x; \
80 smp_mb(); \
30 switch (sizeof(*(ptr))) { \ 81 switch (sizeof(*(ptr))) { \
31 case 4: \ 82 case 4: \
32 __x = (typeof(__x))(typeof(__x-__x))atomic_xchg( \ 83 __x = (typeof(__x))(unsigned long) \
33 (atomic_t *)(ptr), \ 84 __insn_exch4((ptr), (u32)(unsigned long)(n)); \
34 (u32)(typeof((x)-(x)))(x)); \
35 break; \ 85 break; \
36 case 8: \ 86 case 8: \
37 __x = (typeof(__x))(typeof(__x-__x))atomic64_xchg( \ 87 __x = (typeof(__x)) \
38 (atomic64_t *)(ptr), \ 88 __insn_exch((ptr), (unsigned long)(n)); \
39 (u64)(typeof((x)-(x)))(x)); \
40 break; \ 89 break; \
41 default: \ 90 default: \
42 __xchg_called_with_bad_pointer(); \ 91 __xchg_called_with_bad_pointer(); \
92 break; \
43 } \ 93 } \
94 smp_mb(); \
44 __x; \ 95 __x; \
45 }) 96 })
46 97
47#define cmpxchg(ptr, o, n) \ 98#define cmpxchg(ptr, o, n) \
48 ({ \ 99 ({ \
49 typeof(*(ptr)) __x; \ 100 typeof(*(ptr)) __x; \
101 __insn_mtspr(SPR_CMPEXCH_VALUE, (unsigned long)(o)); \
102 smp_mb(); \
50 switch (sizeof(*(ptr))) { \ 103 switch (sizeof(*(ptr))) { \
51 case 4: \ 104 case 4: \
52 __x = (typeof(__x))(typeof(__x-__x))atomic_cmpxchg( \ 105 __x = (typeof(__x))(unsigned long) \
53 (atomic_t *)(ptr), \ 106 __insn_cmpexch4((ptr), (u32)(unsigned long)(n)); \
54 (u32)(typeof((o)-(o)))(o), \
55 (u32)(typeof((n)-(n)))(n)); \
56 break; \ 107 break; \
57 case 8: \ 108 case 8: \
58 __x = (typeof(__x))(typeof(__x-__x))atomic64_cmpxchg( \ 109 __x = (typeof(__x))__insn_cmpexch((ptr), (u64)(n)); \
59 (atomic64_t *)(ptr), \
60 (u64)(typeof((o)-(o)))(o), \
61 (u64)(typeof((n)-(n)))(n)); \
62 break; \ 110 break; \
63 default: \ 111 default: \
64 __cmpxchg_called_with_bad_pointer(); \ 112 __cmpxchg_called_with_bad_pointer(); \
113 break; \
65 } \ 114 } \
115 smp_mb(); \
66 __x; \ 116 __x; \
67 }) 117 })
68 118
69#define tas(ptr) (xchg((ptr), 1)) 119#define xchg64 xchg
120#define cmpxchg64 cmpxchg
70 121
71#define cmpxchg64(ptr, o, n) \ 122#endif
72({ \ 123
73 BUILD_BUG_ON(sizeof(*(ptr)) != 8); \ 124#define tas(ptr) xchg((ptr), 1)
74 cmpxchg((ptr), (o), (n)); \
75})
76 125
77#endif /* __ASSEMBLY__ */ 126#endif /* __ASSEMBLY__ */
78 127