diff options
| author | Davidlohr Bueso <dave@stgolabs.net> | 2015-01-30 04:14:25 -0500 |
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2015-02-18 10:57:13 -0500 |
| commit | 7a215f89a0335582292ec6f3edaa3abd570da75a (patch) | |
| tree | e2f21b6e285b864eab87f5a13a1cbf91b2152eb4 /kernel/locking | |
| parent | 49e4b2bcf7b812e985e65b6c8a0255b1520a6e7e (diff) | |
locking/rwsem: Set lock ownership ASAP
In order to optimize the spinning step, we need to set the lock
owner as soon as the lock is acquired; after a successful counter
cmpxchg operation, that is. This is particularly useful as rwsems
need to set the owner to nil for readers, so there is a greater
chance of falling out of the spinning. Currently we only set the
owner much later in the game, in the more generic level -- latency
can be specially bad when waiting for a node->next pointer when
releasing the osq in up_write calls.
As such, update the owner inside rwsem_try_write_lock (when the
lock is obtained after blocking) and rwsem_try_write_lock_unqueued
(when the lock is obtained while spinning). This requires creating
a new internal rwsem.h header to share the owner related calls.
Also cleanup some headers for mutex and rwsem.
Suggested-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Davidlohr Bueso <dbueso@suse.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Jason Low <jason.low2@hp.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Michel Lespinasse <walken@google.com>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Tim Chen <tim.c.chen@linux.intel.com>
Link: http://lkml.kernel.org/r/1422609267-15102-4-git-send-email-dave@stgolabs.net
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/locking')
| -rw-r--r-- | kernel/locking/mutex.c | 2 | ||||
| -rw-r--r-- | kernel/locking/rwsem-xadd.c | 8 | ||||
| -rw-r--r-- | kernel/locking/rwsem.c | 22 | ||||
| -rw-r--r-- | kernel/locking/rwsem.h | 20 |
4 files changed, 28 insertions, 24 deletions
diff --git a/kernel/locking/mutex.c b/kernel/locking/mutex.c index 59cd6c30421e..43bf25ef3c81 100644 --- a/kernel/locking/mutex.c +++ b/kernel/locking/mutex.c | |||
| @@ -25,7 +25,7 @@ | |||
| 25 | #include <linux/spinlock.h> | 25 | #include <linux/spinlock.h> |
| 26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
| 27 | #include <linux/debug_locks.h> | 27 | #include <linux/debug_locks.h> |
| 28 | #include "mcs_spinlock.h" | 28 | #include <linux/osq_lock.h> |
| 29 | 29 | ||
| 30 | /* | 30 | /* |
| 31 | * In the DEBUG case we are using the "NULL fastpath" for mutexes, | 31 | * In the DEBUG case we are using the "NULL fastpath" for mutexes, |
diff --git a/kernel/locking/rwsem-xadd.c b/kernel/locking/rwsem-xadd.c index 82aba467564a..07713e5d9713 100644 --- a/kernel/locking/rwsem-xadd.c +++ b/kernel/locking/rwsem-xadd.c | |||
| @@ -14,8 +14,9 @@ | |||
| 14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
| 15 | #include <linux/export.h> | 15 | #include <linux/export.h> |
| 16 | #include <linux/sched/rt.h> | 16 | #include <linux/sched/rt.h> |
| 17 | #include <linux/osq_lock.h> | ||
| 17 | 18 | ||
| 18 | #include "mcs_spinlock.h" | 19 | #include "rwsem.h" |
| 19 | 20 | ||
| 20 | /* | 21 | /* |
| 21 | * Guide to the rw_semaphore's count field for common values. | 22 | * Guide to the rw_semaphore's count field for common values. |
| @@ -265,6 +266,7 @@ static inline bool rwsem_try_write_lock(long count, struct rw_semaphore *sem) | |||
| 265 | RWSEM_ACTIVE_WRITE_BIAS) == RWSEM_WAITING_BIAS) { | 266 | RWSEM_ACTIVE_WRITE_BIAS) == RWSEM_WAITING_BIAS) { |
| 266 | if (!list_is_singular(&sem->wait_list)) | 267 | if (!list_is_singular(&sem->wait_list)) |
| 267 | rwsem_atomic_update(RWSEM_WAITING_BIAS, sem); | 268 | rwsem_atomic_update(RWSEM_WAITING_BIAS, sem); |
| 269 | rwsem_set_owner(sem); | ||
| 268 | return true; | 270 | return true; |
| 269 | } | 271 | } |
| 270 | 272 | ||
| @@ -284,8 +286,10 @@ static inline bool rwsem_try_write_lock_unqueued(struct rw_semaphore *sem) | |||
| 284 | return false; | 286 | return false; |
| 285 | 287 | ||
| 286 | old = cmpxchg(&sem->count, count, count + RWSEM_ACTIVE_WRITE_BIAS); | 288 | old = cmpxchg(&sem->count, count, count + RWSEM_ACTIVE_WRITE_BIAS); |
| 287 | if (old == count) | 289 | if (old == count) { |
| 290 | rwsem_set_owner(sem); | ||
| 288 | return true; | 291 | return true; |
| 292 | } | ||
| 289 | 293 | ||
| 290 | count = old; | 294 | count = old; |
| 291 | } | 295 | } |
diff --git a/kernel/locking/rwsem.c b/kernel/locking/rwsem.c index e2d3bc7f03b4..205be0ce34de 100644 --- a/kernel/locking/rwsem.c +++ b/kernel/locking/rwsem.c | |||
| @@ -9,29 +9,9 @@ | |||
| 9 | #include <linux/sched.h> | 9 | #include <linux/sched.h> |
| 10 | #include <linux/export.h> | 10 | #include <linux/export.h> |
| 11 | #include <linux/rwsem.h> | 11 | #include <linux/rwsem.h> |
| 12 | |||
| 13 | #include <linux/atomic.h> | 12 | #include <linux/atomic.h> |
| 14 | 13 | ||
| 15 | #ifdef CONFIG_RWSEM_SPIN_ON_OWNER | 14 | #include "rwsem.h" |
| 16 | static inline void rwsem_set_owner(struct rw_semaphore *sem) | ||
| 17 | { | ||
| 18 | sem->owner = current; | ||
| 19 | } | ||
| 20 | |||
| 21 | static inline void rwsem_clear_owner(struct rw_semaphore *sem) | ||
| 22 | { | ||
| 23 | sem->owner = NULL; | ||
| 24 | } | ||
| 25 | |||
| 26 | #else | ||
| 27 | static inline void rwsem_set_owner(struct rw_semaphore *sem) | ||
| 28 | { | ||
| 29 | } | ||
| 30 | |||
| 31 | static inline void rwsem_clear_owner(struct rw_semaphore *sem) | ||
| 32 | { | ||
| 33 | } | ||
| 34 | #endif | ||
| 35 | 15 | ||
| 36 | /* | 16 | /* |
| 37 | * lock for reading | 17 | * lock for reading |
diff --git a/kernel/locking/rwsem.h b/kernel/locking/rwsem.h new file mode 100644 index 000000000000..870ed9a5b426 --- /dev/null +++ b/kernel/locking/rwsem.h | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | #ifdef CONFIG_RWSEM_SPIN_ON_OWNER | ||
| 2 | static inline void rwsem_set_owner(struct rw_semaphore *sem) | ||
| 3 | { | ||
| 4 | sem->owner = current; | ||
| 5 | } | ||
| 6 | |||
| 7 | static inline void rwsem_clear_owner(struct rw_semaphore *sem) | ||
| 8 | { | ||
| 9 | sem->owner = NULL; | ||
| 10 | } | ||
| 11 | |||
| 12 | #else | ||
| 13 | static inline void rwsem_set_owner(struct rw_semaphore *sem) | ||
| 14 | { | ||
| 15 | } | ||
| 16 | |||
| 17 | static inline void rwsem_clear_owner(struct rw_semaphore *sem) | ||
| 18 | { | ||
| 19 | } | ||
| 20 | #endif | ||
