diff options
| author | Peter Zijlstra <peterz@infradead.org> | 2016-04-04 04:57:12 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2016-06-14 05:54:27 -0400 |
| commit | 1f03e8d2919270bd6ef64f39a45ce8df8a9f012a (patch) | |
| tree | 0cdd5de370212a021d0a1a3439bbc4b0a77fea8b /kernel/locking | |
| parent | 245050c287a9176cee9f98109df101909c1eeef4 (diff) | |
locking/barriers: Replace smp_cond_acquire() with smp_cond_load_acquire()
This new form allows using hardware assisted waiting.
Some hardware (ARM64 and x86) allow monitoring an address for changes,
so by providing a pointer we can use this to replace the cpu_relax()
with hardware optimized methods in the future.
Requested-by: Will Deacon <will.deacon@arm.com>
Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/locking')
| -rw-r--r-- | kernel/locking/qspinlock.c | 12 |
1 files changed, 6 insertions, 6 deletions
diff --git a/kernel/locking/qspinlock.c b/kernel/locking/qspinlock.c index 2f9153b183c9..1b8dda90ebfa 100644 --- a/kernel/locking/qspinlock.c +++ b/kernel/locking/qspinlock.c | |||
| @@ -475,7 +475,7 @@ void queued_spin_lock_slowpath(struct qspinlock *lock, u32 val) | |||
| 475 | * sequentiality; this is because not all clear_pending_set_locked() | 475 | * sequentiality; this is because not all clear_pending_set_locked() |
| 476 | * implementations imply full barriers. | 476 | * implementations imply full barriers. |
| 477 | */ | 477 | */ |
| 478 | smp_cond_acquire(!(atomic_read(&lock->val) & _Q_LOCKED_MASK)); | 478 | smp_cond_load_acquire(&lock->val.counter, !(VAL & _Q_LOCKED_MASK)); |
| 479 | 479 | ||
| 480 | /* | 480 | /* |
| 481 | * take ownership and clear the pending bit. | 481 | * take ownership and clear the pending bit. |
| @@ -562,7 +562,7 @@ queue: | |||
| 562 | * | 562 | * |
| 563 | * The PV pv_wait_head_or_lock function, if active, will acquire | 563 | * The PV pv_wait_head_or_lock function, if active, will acquire |
| 564 | * the lock and return a non-zero value. So we have to skip the | 564 | * the lock and return a non-zero value. So we have to skip the |
| 565 | * smp_cond_acquire() call. As the next PV queue head hasn't been | 565 | * smp_cond_load_acquire() call. As the next PV queue head hasn't been |
| 566 | * designated yet, there is no way for the locked value to become | 566 | * designated yet, there is no way for the locked value to become |
| 567 | * _Q_SLOW_VAL. So both the set_locked() and the | 567 | * _Q_SLOW_VAL. So both the set_locked() and the |
| 568 | * atomic_cmpxchg_relaxed() calls will be safe. | 568 | * atomic_cmpxchg_relaxed() calls will be safe. |
| @@ -573,7 +573,7 @@ queue: | |||
| 573 | if ((val = pv_wait_head_or_lock(lock, node))) | 573 | if ((val = pv_wait_head_or_lock(lock, node))) |
| 574 | goto locked; | 574 | goto locked; |
| 575 | 575 | ||
| 576 | smp_cond_acquire(!((val = atomic_read(&lock->val)) & _Q_LOCKED_PENDING_MASK)); | 576 | val = smp_cond_load_acquire(&lock->val.counter, !(VAL & _Q_LOCKED_PENDING_MASK)); |
| 577 | 577 | ||
| 578 | locked: | 578 | locked: |
| 579 | /* | 579 | /* |
| @@ -593,9 +593,9 @@ locked: | |||
| 593 | break; | 593 | break; |
| 594 | } | 594 | } |
| 595 | /* | 595 | /* |
| 596 | * The smp_cond_acquire() call above has provided the necessary | 596 | * The smp_cond_load_acquire() call above has provided the |
| 597 | * acquire semantics required for locking. At most two | 597 | * necessary acquire semantics required for locking. At most |
| 598 | * iterations of this loop may be ran. | 598 | * two iterations of this loop may be ran. |
| 599 | */ | 599 | */ |
| 600 | old = atomic_cmpxchg_relaxed(&lock->val, val, _Q_LOCKED_VAL); | 600 | old = atomic_cmpxchg_relaxed(&lock->val, val, _Q_LOCKED_VAL); |
| 601 | if (old == val) | 601 | if (old == val) |
