diff options
Diffstat (limited to 'arch/tile/include/asm/cmpxchg.h')
-rw-r--r-- | arch/tile/include/asm/cmpxchg.h | 97 |
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> |
24 | extern unsigned long __xchg_called_with_bad_pointer(void); | ||
25 | extern unsigned long __cmpxchg_called_with_bad_pointer(void); | ||
26 | 24 | ||
27 | #define xchg(ptr, x) \ | 25 | /* Nonexistent functions intended to cause compile errors. */ |
26 | extern void __xchg_called_with_bad_pointer(void) | ||
27 | __compiletime_error("Bad argument size for xchg"); | ||
28 | extern 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(). */ | ||
34 | int _atomic_xchg(int *ptr, int n); | ||
35 | int _atomic_xchg_add(int *v, int i); | ||
36 | int _atomic_xchg_add_unless(int *v, int a, int u); | ||
37 | int _atomic_cmpxchg(int *ptr, int o, int n); | ||
38 | u64 _atomic64_xchg(u64 *v, u64 n); | ||
39 | u64 _atomic64_xchg_add(u64 *v, u64 i); | ||
40 | u64 _atomic64_xchg_add_unless(u64 *v, u64 a, u64 u); | ||
41 | u64 _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 | ||