Skip to content

Commit

Permalink
ARM: 7812/1: rwlocks: retry trylock operation if strex fails on free …
Browse files Browse the repository at this point in the history
…lock

Commit 15e7e5c ("ARM: 7749/1: spinlock: retry trylock operation if
strex fails on free lock") modifying our arch_spin_trylock to retry the
acquisition if the lock appeared uncontended, but the strex failed.

This patch does the same for rwlocks, which were missed by the original
patch.

Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
  • Loading branch information
Will Deacon authored and Russell King committed Aug 13, 2013
1 parent afa31d8 commit 00efaa0
Showing 1 changed file with 30 additions and 19 deletions.
49 changes: 30 additions & 19 deletions arch/arm/include/asm/spinlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,17 +168,20 @@ static inline void arch_write_lock(arch_rwlock_t *rw)

static inline int arch_write_trylock(arch_rwlock_t *rw)
{
unsigned long tmp;
unsigned long contended, res;

__asm__ __volatile__(
" ldrex %0, [%1]\n"
" teq %0, #0\n"
" strexeq %0, %2, [%1]"
: "=&r" (tmp)
: "r" (&rw->lock), "r" (0x80000000)
: "cc");
do {
__asm__ __volatile__(
" ldrex %0, [%2]\n"
" mov %1, #0\n"
" teq %0, #0\n"
" strexeq %1, %3, [%2]"
: "=&r" (contended), "=&r" (res)
: "r" (&rw->lock), "r" (0x80000000)
: "cc");
} while (res);

if (tmp == 0) {
if (!contended) {
smp_mb();
return 1;
} else {
Expand Down Expand Up @@ -254,18 +257,26 @@ static inline void arch_read_unlock(arch_rwlock_t *rw)

static inline int arch_read_trylock(arch_rwlock_t *rw)
{
unsigned long tmp, tmp2 = 1;
unsigned long contended, res;

__asm__ __volatile__(
" ldrex %0, [%2]\n"
" adds %0, %0, #1\n"
" strexpl %1, %0, [%2]\n"
: "=&r" (tmp), "+r" (tmp2)
: "r" (&rw->lock)
: "cc");
do {
__asm__ __volatile__(
" ldrex %0, [%2]\n"
" mov %1, #0\n"
" adds %0, %0, #1\n"
" strexpl %1, %0, [%2]"
: "=&r" (contended), "=&r" (res)
: "r" (&rw->lock)
: "cc");
} while (res);

smp_mb();
return tmp2 == 0;
/* If the lock is negative, then it is already held for write. */
if (contended < 0x80000000) {
smp_mb();
return 1;
} else {
return 0;
}
}

/* read_can_lock - would read_trylock() succeed? */
Expand Down

0 comments on commit 00efaa0

Please sign in to comment.