aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/include/asm/spinlock.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/include/asm/spinlock.h')
-rw-r--r--arch/arm/include/asm/spinlock.h53
1 files changed, 32 insertions, 21 deletions
diff --git a/arch/arm/include/asm/spinlock.h b/arch/arm/include/asm/spinlock.h
index f8b8965666e9..4f2c28060c9a 100644
--- a/arch/arm/include/asm/spinlock.h
+++ b/arch/arm/include/asm/spinlock.h
@@ -46,7 +46,7 @@ static inline void dsb_sev(void)
46{ 46{
47#if __LINUX_ARM_ARCH__ >= 7 47#if __LINUX_ARM_ARCH__ >= 7
48 __asm__ __volatile__ ( 48 __asm__ __volatile__ (
49 "dsb\n" 49 "dsb ishst\n"
50 SEV 50 SEV
51 ); 51 );
52#else 52#else
@@ -107,7 +107,7 @@ static inline int arch_spin_trylock(arch_spinlock_t *lock)
107 " subs %1, %0, %0, ror #16\n" 107 " subs %1, %0, %0, ror #16\n"
108 " addeq %0, %0, %4\n" 108 " addeq %0, %0, %4\n"
109 " strexeq %2, %0, [%3]" 109 " strexeq %2, %0, [%3]"
110 : "=&r" (slock), "=&r" (contended), "=r" (res) 110 : "=&r" (slock), "=&r" (contended), "=&r" (res)
111 : "r" (&lock->slock), "I" (1 << TICKET_SHIFT) 111 : "r" (&lock->slock), "I" (1 << TICKET_SHIFT)
112 : "cc"); 112 : "cc");
113 } while (res); 113 } while (res);
@@ -168,17 +168,20 @@ static inline void arch_write_lock(arch_rwlock_t *rw)
168 168
169static inline int arch_write_trylock(arch_rwlock_t *rw) 169static inline int arch_write_trylock(arch_rwlock_t *rw)
170{ 170{
171 unsigned long tmp; 171 unsigned long contended, res;
172 172
173 __asm__ __volatile__( 173 do {
174" ldrex %0, [%1]\n" 174 __asm__ __volatile__(
175" teq %0, #0\n" 175 " ldrex %0, [%2]\n"
176" strexeq %0, %2, [%1]" 176 " mov %1, #0\n"
177 : "=&r" (tmp) 177 " teq %0, #0\n"
178 : "r" (&rw->lock), "r" (0x80000000) 178 " strexeq %1, %3, [%2]"
179 : "cc"); 179 : "=&r" (contended), "=&r" (res)
180 : "r" (&rw->lock), "r" (0x80000000)
181 : "cc");
182 } while (res);
180 183
181 if (tmp == 0) { 184 if (!contended) {
182 smp_mb(); 185 smp_mb();
183 return 1; 186 return 1;
184 } else { 187 } else {
@@ -254,18 +257,26 @@ static inline void arch_read_unlock(arch_rwlock_t *rw)
254 257
255static inline int arch_read_trylock(arch_rwlock_t *rw) 258static inline int arch_read_trylock(arch_rwlock_t *rw)
256{ 259{
257 unsigned long tmp, tmp2 = 1; 260 unsigned long contended, res;
258 261
259 __asm__ __volatile__( 262 do {
260" ldrex %0, [%2]\n" 263 __asm__ __volatile__(
261" adds %0, %0, #1\n" 264 " ldrex %0, [%2]\n"
262" strexpl %1, %0, [%2]\n" 265 " mov %1, #0\n"
263 : "=&r" (tmp), "+r" (tmp2) 266 " adds %0, %0, #1\n"
264 : "r" (&rw->lock) 267 " strexpl %1, %0, [%2]"
265 : "cc"); 268 : "=&r" (contended), "=&r" (res)
269 : "r" (&rw->lock)
270 : "cc");
271 } while (res);
266 272
267 smp_mb(); 273 /* If the lock is negative, then it is already held for write. */
268 return tmp2 == 0; 274 if (contended < 0x80000000) {
275 smp_mb();
276 return 1;
277 } else {
278 return 0;
279 }
269} 280}
270 281
271/* read_can_lock - would read_trylock() succeed? */ 282/* read_can_lock - would read_trylock() succeed? */