|
@@ -107,7 +107,7 @@ static inline int arch_spin_trylock(arch_spinlock_t *lock)
|
|
|
" subs %1, %0, %0, ror #16\n"
|
|
|
" addeq %0, %0, %4\n"
|
|
|
" strexeq %2, %0, [%3]"
|
|
|
- : "=&r" (slock), "=&r" (contended), "=r" (res)
|
|
|
+ : "=&r" (slock), "=&r" (contended), "=&r" (res)
|
|
|
: "r" (&lock->slock), "I" (1 << TICKET_SHIFT)
|
|
|
: "cc");
|
|
|
} while (res);
|
|
@@ -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 {
|
|
@@ -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? */
|