diff options
author | Andreas Larsson <andreas@gaisler.com> | 2014-11-05 09:52:08 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-11-07 15:51:44 -0500 |
commit | 1a17fdc4f4ed06b63fac1937470378a5441a663a (patch) | |
tree | 1590a724b9a40458ba1a990ceb41fc51839196fc /arch/sparc/lib/atomic32.c | |
parent | ab5c780913bca0a5763ca05dd5c2cb5cb08ccb26 (diff) |
sparc32: Implement xchg and atomic_xchg using ATOMIC_HASH locks
Atomicity between xchg and cmpxchg cannot be guaranteed when xchg is
implemented with a swap and cmpxchg is implemented with locks.
Without this, e.g. mcs_spin_lock and mcs_spin_unlock are broken.
Signed-off-by: Andreas Larsson <andreas@gaisler.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc/lib/atomic32.c')
-rw-r--r-- | arch/sparc/lib/atomic32.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/arch/sparc/lib/atomic32.c b/arch/sparc/lib/atomic32.c index a7c418ac26af..71cd65ab200c 100644 --- a/arch/sparc/lib/atomic32.c +++ b/arch/sparc/lib/atomic32.c | |||
@@ -45,6 +45,19 @@ ATOMIC_OP(add, +=) | |||
45 | 45 | ||
46 | #undef ATOMIC_OP | 46 | #undef ATOMIC_OP |
47 | 47 | ||
48 | int atomic_xchg(atomic_t *v, int new) | ||
49 | { | ||
50 | int ret; | ||
51 | unsigned long flags; | ||
52 | |||
53 | spin_lock_irqsave(ATOMIC_HASH(v), flags); | ||
54 | ret = v->counter; | ||
55 | v->counter = new; | ||
56 | spin_unlock_irqrestore(ATOMIC_HASH(v), flags); | ||
57 | return ret; | ||
58 | } | ||
59 | EXPORT_SYMBOL(atomic_xchg); | ||
60 | |||
48 | int atomic_cmpxchg(atomic_t *v, int old, int new) | 61 | int atomic_cmpxchg(atomic_t *v, int old, int new) |
49 | { | 62 | { |
50 | int ret; | 63 | int ret; |
@@ -137,3 +150,17 @@ unsigned long __cmpxchg_u32(volatile u32 *ptr, u32 old, u32 new) | |||
137 | return (unsigned long)prev; | 150 | return (unsigned long)prev; |
138 | } | 151 | } |
139 | EXPORT_SYMBOL(__cmpxchg_u32); | 152 | EXPORT_SYMBOL(__cmpxchg_u32); |
153 | |||
154 | unsigned long __xchg_u32(volatile u32 *ptr, u32 new) | ||
155 | { | ||
156 | unsigned long flags; | ||
157 | u32 prev; | ||
158 | |||
159 | spin_lock_irqsave(ATOMIC_HASH(ptr), flags); | ||
160 | prev = *ptr; | ||
161 | *ptr = new; | ||
162 | spin_unlock_irqrestore(ATOMIC_HASH(ptr), flags); | ||
163 | |||
164 | return (unsigned long)prev; | ||
165 | } | ||
166 | EXPORT_SYMBOL(__xchg_u32); | ||