From: Waiman Long <longman@redhat.com>
To: Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@redhat.com>, Will Deacon <will.deacon@arm.com>,
Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org, x86@kernel.org,
Davidlohr Bueso <dave@stgolabs.net>,
Linus Torvalds <torvalds@linux-foundation.org>,
Tim Chen <tim.c.chen@linux.intel.com>,
huang ying <huang.ying.caritas@gmail.com>,
Waiman Long <longman@redhat.com>
Subject: [PATCH-tip v3 11/14] locking/rwsem: Add more rwsem owner access helpers
Date: Wed, 10 Apr 2019 14:42:28 -0400 [thread overview]
Message-ID: <20190410184231.6748-12-longman@redhat.com> (raw)
In-Reply-To: <20190410184231.6748-1-longman@redhat.com>
Before combining owner and count, we are adding two new helpers for
accessing the owner value in the rwsem.
1) struct task_struct *rwsem_get_owner(struct rw_semaphore *sem)
2) bool is_rwsem_reader_owned(struct rw_semaphore *sem)
Signed-off-by: Waiman Long <longman@redhat.com>
---
kernel/locking/rwsem-xadd.c | 15 ++++++++++-----
kernel/locking/rwsem.c | 3 +--
kernel/locking/rwsem.h | 32 ++++++++++++++++++++++++++------
3 files changed, 37 insertions(+), 13 deletions(-)
diff --git a/kernel/locking/rwsem-xadd.c b/kernel/locking/rwsem-xadd.c
index 09b245e0d6f4..196729fd7f94 100644
--- a/kernel/locking/rwsem-xadd.c
+++ b/kernel/locking/rwsem-xadd.c
@@ -312,7 +312,7 @@ static inline bool rwsem_can_spin_on_owner(struct rw_semaphore *sem)
preempt_disable();
rcu_read_lock();
- owner = READ_ONCE(sem->owner);
+ owner = rwsem_get_owner(sem);
if (owner) {
ret = is_rwsem_owner_spinnable(owner) &&
(is_rwsem_owner_reader(owner) || owner_on_cpu(owner));
@@ -344,15 +344,21 @@ enum owner_state {
static noinline enum owner_state rwsem_spin_on_owner(struct rw_semaphore *sem)
{
- struct task_struct *owner = READ_ONCE(sem->owner);
+ struct task_struct *owner = rwsem_get_owner(sem);
long count;
if (!is_rwsem_owner_spinnable(owner))
return OWNER_NONSPINNABLE;
rcu_read_lock();
- while (owner && !is_rwsem_owner_reader(owner)
- && (READ_ONCE(sem->owner) == owner)) {
+ while (owner && !is_rwsem_owner_reader(owner)) {
+ struct task_struct *new_owner = rwsem_get_owner(sem);
+
+ if (new_owner != owner) {
+ owner = new_owner;
+ break; /* The owner has changed */
+ }
+
/*
* Ensure we emit the owner->on_cpu, dereference _after_
* checking sem->owner still matches owner, if that fails,
@@ -379,7 +385,6 @@ static noinline enum owner_state rwsem_spin_on_owner(struct rw_semaphore *sem)
* spinning except when here is no active locks and the handoff bit
* is set. In this case, we have to stop spinning.
*/
- owner = READ_ONCE(sem->owner);
if (!is_rwsem_owner_spinnable(owner))
return OWNER_NONSPINNABLE;
if (owner && !is_rwsem_owner_reader(owner))
diff --git a/kernel/locking/rwsem.c b/kernel/locking/rwsem.c
index ccbf18f560ff..38d24676e01c 100644
--- a/kernel/locking/rwsem.c
+++ b/kernel/locking/rwsem.c
@@ -198,8 +198,7 @@ EXPORT_SYMBOL(down_write_killable_nested);
void up_read_non_owner(struct rw_semaphore *sem)
{
- DEBUG_RWSEMS_WARN_ON(!((unsigned long)sem->owner & RWSEM_READER_OWNED),
- sem);
+ DEBUG_RWSEMS_WARN_ON(!is_rwsem_reader_owned(sem), sem);
__up_read(sem);
}
diff --git a/kernel/locking/rwsem.h b/kernel/locking/rwsem.h
index 19ae51ff7b91..ef7287f273fe 100644
--- a/kernel/locking/rwsem.h
+++ b/kernel/locking/rwsem.h
@@ -92,6 +92,11 @@ static inline void rwsem_clear_owner(struct rw_semaphore *sem)
WRITE_ONCE(sem->owner, NULL);
}
+static inline struct task_struct *rwsem_get_owner(struct rw_semaphore *sem)
+{
+ return READ_ONCE(sem->owner);
+}
+
/*
* The task_struct pointer of the last owning reader will be left in
* the owner field.
@@ -136,6 +141,23 @@ static inline bool is_rwsem_spinnable(struct rw_semaphore *sem)
return is_rwsem_owner_spinnable(READ_ONCE(sem->owner));
}
+/*
+ * Return true if the rwsem is owned by a reader.
+ */
+static inline bool is_rwsem_reader_owned(struct rw_semaphore *sem)
+{
+#ifdef CONFIG_DEBUG_RWSEMS
+ /*
+ * Check the count to see if it is write-locked.
+ */
+ long count = atomic_long_read(&sem->count);
+
+ if (count & RWSEM_WRITER_MASK)
+ return false;
+#endif
+ return (unsigned long)sem->owner & RWSEM_READER_OWNED;
+}
+
/*
* Return true if rwsem is owned by an anonymous writer or readers.
*/
@@ -155,6 +177,7 @@ static inline void rwsem_clear_reader_owned(struct rw_semaphore *sem)
{
unsigned long val = (unsigned long)current | RWSEM_READER_OWNED
| RWSEM_ANONYMOUSLY_OWNED;
+
if (READ_ONCE(sem->owner) == (struct task_struct *)val)
cmpxchg_relaxed((unsigned long *)&sem->owner, val,
RWSEM_READER_OWNED | RWSEM_ANONYMOUSLY_OWNED);
@@ -196,8 +219,7 @@ static inline void __down_read(struct rw_semaphore *sem)
if (unlikely(atomic_long_fetch_add_acquire(RWSEM_READER_BIAS,
&sem->count) & RWSEM_READ_FAILED_MASK)) {
rwsem_down_read_failed(sem);
- DEBUG_RWSEMS_WARN_ON(!((unsigned long)sem->owner &
- RWSEM_READER_OWNED), sem);
+ DEBUG_RWSEMS_WARN_ON(!is_rwsem_reader_owned(sem), sem);
} else {
rwsem_set_reader_owned(sem);
}
@@ -209,8 +231,7 @@ static inline int __down_read_killable(struct rw_semaphore *sem)
&sem->count) & RWSEM_READ_FAILED_MASK)) {
if (IS_ERR(rwsem_down_read_failed_killable(sem)))
return -EINTR;
- DEBUG_RWSEMS_WARN_ON(!((unsigned long)sem->owner &
- RWSEM_READER_OWNED), sem);
+ DEBUG_RWSEMS_WARN_ON(!is_rwsem_reader_owned(sem), sem);
} else {
rwsem_set_reader_owned(sem);
}
@@ -277,8 +298,7 @@ static inline void __up_read(struct rw_semaphore *sem)
{
long tmp;
- DEBUG_RWSEMS_WARN_ON(!((unsigned long)sem->owner & RWSEM_READER_OWNED),
- sem);
+ DEBUG_RWSEMS_WARN_ON(!is_rwsem_reader_owned(sem), sem);
rwsem_clear_reader_owned(sem);
tmp = atomic_long_add_return_release(-RWSEM_READER_BIAS, &sem->count);
if (unlikely((tmp & (RWSEM_LOCK_MASK|RWSEM_FLAG_WAITERS))
--
2.18.1
next prev parent reply other threads:[~2019-04-10 18:43 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-04-10 18:42 [PATCH-tip v3 00/14] locking/rwsem: Rwsem rearchitecture part 2 Waiman Long
2019-04-10 18:42 ` [PATCH-tip v3 01/14] locking/rwsem: Prevent unneeded warning during locking selftest Waiman Long
2019-04-10 18:42 ` [PATCH-tip v3 02/14] locking/rwsem: Make owner available even if !CONFIG_RWSEM_SPIN_ON_OWNER Waiman Long
2019-04-11 8:12 ` Peter Zijlstra
2019-04-11 16:03 ` Waiman Long
2019-04-12 7:02 ` Ingo Molnar
2019-04-12 7:05 ` Peter Zijlstra
2019-04-12 7:09 ` Ingo Molnar
2019-04-12 14:04 ` Waiman Long
2019-04-12 14:07 ` Waiman Long
2019-04-12 14:22 ` Waiman Long
2019-04-12 16:41 ` Ingo Molnar
2019-04-12 18:05 ` Waiman Long
2019-04-13 2:24 ` Waiman Long
2019-04-15 13:43 ` Waiman Long
2019-04-16 7:53 ` Ingo Molnar
2019-04-12 18:21 ` Peter Zijlstra
2019-04-10 18:42 ` [PATCH-tip v3 03/14] locking/rwsem: Implement a new locking scheme Waiman Long
2019-04-10 18:42 ` [PATCH-tip v3 04/14] locking/rwsem: Implement lock handoff to prevent lock starvation Waiman Long
2019-04-10 19:38 ` Peter Zijlstra
2019-04-10 20:28 ` Waiman Long
2019-04-10 18:42 ` [PATCH-tip v3 05/14] locking/rwsem: Remove rwsem_wake() wakeup optimization Waiman Long
2019-04-11 7:25 ` Peter Zijlstra
2019-04-11 15:55 ` Waiman Long
2019-04-10 18:42 ` [PATCH-tip v3 06/14] locking/rwsem: Make rwsem_spin_on_owner() return owner state Waiman Long
2019-04-10 18:42 ` [PATCH-tip v3 07/14] locking/rwsem: Ensure an RT task will not spin on reader Waiman Long
2019-04-10 18:42 ` [PATCH-tip v3 08/14] locking/rwsem: Wake up almost all readers in wait queue Waiman Long
2019-04-10 18:42 ` [PATCH-tip v3 09/14] locking/rwsem: Enable readers spinning on writer Waiman Long
2019-04-10 18:42 ` [PATCH-tip v3 10/14] locking/rwsem: Enable time-based spinning on reader-owned rwsem Waiman Long
2019-04-10 18:42 ` Waiman Long [this message]
2019-04-10 18:42 ` [PATCH-tip v3 12/14] locking/rwsem: Guard against making count negative Waiman Long
2019-04-10 18:42 ` [PATCH-tip v3 13/14] locking/rwsem: Merge owner into count on x86-64 Waiman Long
2019-04-10 18:42 ` [PATCH-tip v3 14/14] locking/rwsem: Remove redundant computation of writer lock word Waiman Long
2019-04-11 8:37 ` [PATCH-tip v3 00/14] locking/rwsem: Rwsem rearchitecture part 2 Peter Zijlstra
2019-04-11 16:09 ` Waiman Long
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190410184231.6748-12-longman@redhat.com \
--to=longman@redhat.com \
--cc=dave@stgolabs.net \
--cc=huang.ying.caritas@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=peterz@infradead.org \
--cc=tglx@linutronix.de \
--cc=tim.c.chen@linux.intel.com \
--cc=torvalds@linux-foundation.org \
--cc=will.deacon@arm.com \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.