diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-13 09:48:00 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-13 09:48:00 -0400 |
commit | dbb885fecc1b1b35e93416bedd24d21bd20f60ed (patch) | |
tree | 9aa92bcc4e3d3594eba0ba85d72b878d85f35a59 /arch/m68k | |
parent | d6dd50e07c5bec00db2005969b1a01f8ca3d25ef (diff) | |
parent | 2291059c852706c6f5ffb400366042b7625066cd (diff) |
Merge branch 'locking-arch-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull arch atomic cleanups from Ingo Molnar:
"This is a series kept separate from the main locking tree, which
cleans up and improves various details in the atomics type handling:
- Remove the unused atomic_or_long() method
- Consolidate and compress atomic ops implementations between
architectures, to reduce linecount and to make it easier to add new
ops.
- Rewrite generic atomic support to only require cmpxchg() from an
architecture - generate all other methods from that"
* 'locking-arch-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (23 commits)
locking,arch: Use ACCESS_ONCE() instead of cast to volatile in atomic_read()
locking, mips: Fix atomics
locking, sparc64: Fix atomics
locking,arch: Rewrite generic atomic support
locking,arch,xtensa: Fold atomic_ops
locking,arch,sparc: Fold atomic_ops
locking,arch,sh: Fold atomic_ops
locking,arch,powerpc: Fold atomic_ops
locking,arch,parisc: Fold atomic_ops
locking,arch,mn10300: Fold atomic_ops
locking,arch,mips: Fold atomic_ops
locking,arch,metag: Fold atomic_ops
locking,arch,m68k: Fold atomic_ops
locking,arch,m32r: Fold atomic_ops
locking,arch,ia64: Fold atomic_ops
locking,arch,hexagon: Fold atomic_ops
locking,arch,cris: Fold atomic_ops
locking,arch,avr32: Fold atomic_ops
locking,arch,arm64: Fold atomic_ops
locking,arch,arm: Fold atomic_ops
...
Diffstat (limited to 'arch/m68k')
-rw-r--r-- | arch/m68k/include/asm/atomic.h | 111 |
1 files changed, 48 insertions, 63 deletions
diff --git a/arch/m68k/include/asm/atomic.h b/arch/m68k/include/asm/atomic.h index 55695212a2ae..e85f047fb072 100644 --- a/arch/m68k/include/asm/atomic.h +++ b/arch/m68k/include/asm/atomic.h | |||
@@ -17,7 +17,7 @@ | |||
17 | 17 | ||
18 | #define ATOMIC_INIT(i) { (i) } | 18 | #define ATOMIC_INIT(i) { (i) } |
19 | 19 | ||
20 | #define atomic_read(v) (*(volatile int *)&(v)->counter) | 20 | #define atomic_read(v) ACCESS_ONCE((v)->counter) |
21 | #define atomic_set(v, i) (((v)->counter) = i) | 21 | #define atomic_set(v, i) (((v)->counter) = i) |
22 | 22 | ||
23 | /* | 23 | /* |
@@ -30,16 +30,57 @@ | |||
30 | #define ASM_DI "di" | 30 | #define ASM_DI "di" |
31 | #endif | 31 | #endif |
32 | 32 | ||
33 | static inline void atomic_add(int i, atomic_t *v) | 33 | #define ATOMIC_OP(op, c_op, asm_op) \ |
34 | { | 34 | static inline void atomic_##op(int i, atomic_t *v) \ |
35 | __asm__ __volatile__("addl %1,%0" : "+m" (*v) : ASM_DI (i)); | 35 | { \ |
36 | __asm__ __volatile__(#asm_op "l %1,%0" : "+m" (*v) : ASM_DI (i));\ | ||
37 | } \ | ||
38 | |||
39 | #ifdef CONFIG_RMW_INSNS | ||
40 | |||
41 | #define ATOMIC_OP_RETURN(op, c_op, asm_op) \ | ||
42 | static inline int atomic_##op##_return(int i, atomic_t *v) \ | ||
43 | { \ | ||
44 | int t, tmp; \ | ||
45 | \ | ||
46 | __asm__ __volatile__( \ | ||
47 | "1: movel %2,%1\n" \ | ||
48 | " " #asm_op "l %3,%1\n" \ | ||
49 | " casl %2,%1,%0\n" \ | ||
50 | " jne 1b" \ | ||
51 | : "+m" (*v), "=&d" (t), "=&d" (tmp) \ | ||
52 | : "g" (i), "2" (atomic_read(v))); \ | ||
53 | return t; \ | ||
36 | } | 54 | } |
37 | 55 | ||
38 | static inline void atomic_sub(int i, atomic_t *v) | 56 | #else |
39 | { | 57 | |
40 | __asm__ __volatile__("subl %1,%0" : "+m" (*v) : ASM_DI (i)); | 58 | #define ATOMIC_OP_RETURN(op, c_op, asm_op) \ |
59 | static inline int atomic_##op##_return(int i, atomic_t * v) \ | ||
60 | { \ | ||
61 | unsigned long flags; \ | ||
62 | int t; \ | ||
63 | \ | ||
64 | local_irq_save(flags); \ | ||
65 | t = (v->counter c_op i); \ | ||
66 | local_irq_restore(flags); \ | ||
67 | \ | ||
68 | return t; \ | ||
41 | } | 69 | } |
42 | 70 | ||
71 | #endif /* CONFIG_RMW_INSNS */ | ||
72 | |||
73 | #define ATOMIC_OPS(op, c_op, asm_op) \ | ||
74 | ATOMIC_OP(op, c_op, asm_op) \ | ||
75 | ATOMIC_OP_RETURN(op, c_op, asm_op) | ||
76 | |||
77 | ATOMIC_OPS(add, +=, add) | ||
78 | ATOMIC_OPS(sub, -=, sub) | ||
79 | |||
80 | #undef ATOMIC_OPS | ||
81 | #undef ATOMIC_OP_RETURN | ||
82 | #undef ATOMIC_OP | ||
83 | |||
43 | static inline void atomic_inc(atomic_t *v) | 84 | static inline void atomic_inc(atomic_t *v) |
44 | { | 85 | { |
45 | __asm__ __volatile__("addql #1,%0" : "+m" (*v)); | 86 | __asm__ __volatile__("addql #1,%0" : "+m" (*v)); |
@@ -76,67 +117,11 @@ static inline int atomic_inc_and_test(atomic_t *v) | |||
76 | 117 | ||
77 | #ifdef CONFIG_RMW_INSNS | 118 | #ifdef CONFIG_RMW_INSNS |
78 | 119 | ||
79 | static inline int atomic_add_return(int i, atomic_t *v) | ||
80 | { | ||
81 | int t, tmp; | ||
82 | |||
83 | __asm__ __volatile__( | ||
84 | "1: movel %2,%1\n" | ||
85 | " addl %3,%1\n" | ||
86 | " casl %2,%1,%0\n" | ||
87 | " jne 1b" | ||
88 | : "+m" (*v), "=&d" (t), "=&d" (tmp) | ||
89 | : "g" (i), "2" (atomic_read(v))); | ||
90 | return t; | ||
91 | } | ||
92 | |||
93 | static inline int atomic_sub_return(int i, atomic_t *v) | ||
94 | { | ||
95 | int t, tmp; | ||
96 | |||
97 | __asm__ __volatile__( | ||
98 | "1: movel %2,%1\n" | ||
99 | " subl %3,%1\n" | ||
100 | " casl %2,%1,%0\n" | ||
101 | " jne 1b" | ||
102 | : "+m" (*v), "=&d" (t), "=&d" (tmp) | ||
103 | : "g" (i), "2" (atomic_read(v))); | ||
104 | return t; | ||
105 | } | ||
106 | |||
107 | #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) | 120 | #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) |
108 | #define atomic_xchg(v, new) (xchg(&((v)->counter), new)) | 121 | #define atomic_xchg(v, new) (xchg(&((v)->counter), new)) |
109 | 122 | ||
110 | #else /* !CONFIG_RMW_INSNS */ | 123 | #else /* !CONFIG_RMW_INSNS */ |
111 | 124 | ||
112 | static inline int atomic_add_return(int i, atomic_t * v) | ||
113 | { | ||
114 | unsigned long flags; | ||
115 | int t; | ||
116 | |||
117 | local_irq_save(flags); | ||
118 | t = atomic_read(v); | ||
119 | t += i; | ||
120 | atomic_set(v, t); | ||
121 | local_irq_restore(flags); | ||
122 | |||
123 | return t; | ||
124 | } | ||
125 | |||
126 | static inline int atomic_sub_return(int i, atomic_t * v) | ||
127 | { | ||
128 | unsigned long flags; | ||
129 | int t; | ||
130 | |||
131 | local_irq_save(flags); | ||
132 | t = atomic_read(v); | ||
133 | t -= i; | ||
134 | atomic_set(v, t); | ||
135 | local_irq_restore(flags); | ||
136 | |||
137 | return t; | ||
138 | } | ||
139 | |||
140 | static inline int atomic_cmpxchg(atomic_t *v, int old, int new) | 125 | static inline int atomic_cmpxchg(atomic_t *v, int old, int new) |
141 | { | 126 | { |
142 | unsigned long flags; | 127 | unsigned long flags; |