Commit 2d9200cf authored by Kent Overstreet's avatar Kent Overstreet

six locks: Use atomic_try_cmpxchg_acquire()

This switches to a newer cmpxchg variant which updates @old for us on
failure, simplifying the cmpxchg loops a bit and supposedly generating
better code.
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent c4687a4a
...@@ -116,7 +116,7 @@ static int __do_six_trylock(struct six_lock *lock, enum six_lock_type type, ...@@ -116,7 +116,7 @@ static int __do_six_trylock(struct six_lock *lock, enum six_lock_type type,
struct task_struct *task, bool try) struct task_struct *task, bool try)
{ {
int ret; int ret;
u32 old, new, v; u32 old;
EBUG_ON(type == SIX_LOCK_write && lock->owner != task); EBUG_ON(type == SIX_LOCK_write && lock->owner != task);
EBUG_ON(type == SIX_LOCK_write && EBUG_ON(type == SIX_LOCK_write &&
...@@ -177,19 +177,14 @@ static int __do_six_trylock(struct six_lock *lock, enum six_lock_type type, ...@@ -177,19 +177,14 @@ static int __do_six_trylock(struct six_lock *lock, enum six_lock_type type,
ret = -1 - SIX_LOCK_read; ret = -1 - SIX_LOCK_read;
} }
} else { } else {
v = atomic_read(&lock->state); old = atomic_read(&lock->state);
do { do {
new = old = v;
ret = !(old & l[type].lock_fail); ret = !(old & l[type].lock_fail);
if (!ret || (type == SIX_LOCK_write && !try)) { if (!ret || (type == SIX_LOCK_write && !try)) {
smp_mb(); smp_mb();
break; break;
} }
} while (!atomic_try_cmpxchg_acquire(&lock->state, &old, old + l[type].lock_val));
new += l[type].lock_val;
} while ((v = atomic_cmpxchg_acquire(&lock->state, old, new)) != old);
EBUG_ON(ret && !(atomic_read(&lock->state) & l[type].held_mask)); EBUG_ON(ret && !(atomic_read(&lock->state) & l[type].held_mask));
} }
...@@ -675,10 +670,10 @@ EXPORT_SYMBOL_GPL(six_lock_downgrade); ...@@ -675,10 +670,10 @@ EXPORT_SYMBOL_GPL(six_lock_downgrade);
*/ */
bool six_lock_tryupgrade(struct six_lock *lock) bool six_lock_tryupgrade(struct six_lock *lock)
{ {
u32 old, new, v = atomic_read(&lock->state); u32 old = atomic_read(&lock->state), new;
do { do {
new = old = v; new = old;
if (new & SIX_LOCK_HELD_intent) if (new & SIX_LOCK_HELD_intent)
return false; return false;
...@@ -689,7 +684,7 @@ bool six_lock_tryupgrade(struct six_lock *lock) ...@@ -689,7 +684,7 @@ bool six_lock_tryupgrade(struct six_lock *lock)
} }
new |= SIX_LOCK_HELD_intent; new |= SIX_LOCK_HELD_intent;
} while ((v = atomic_cmpxchg_acquire(&lock->state, old, new)) != old); } while (!atomic_try_cmpxchg_acquire(&lock->state, &old, new));
if (lock->readers) if (lock->readers)
this_cpu_dec(*lock->readers); this_cpu_dec(*lock->readers);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment