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>,
Waiman Long <longman@redhat.com>
Subject: [PATCH-tip v2 04/12] locking/rwsem: Make rwsem_spin_on_owner() return owner state
Date: Fri, 5 Apr 2019 15:21:07 -0400 [thread overview]
Message-ID: <20190405192115.17416-5-longman@redhat.com> (raw)
In-Reply-To: <20190405192115.17416-1-longman@redhat.com>
This patch modifies rwsem_spin_on_owner() to return four possible
values to better reflect the state of lock holder which enables us to
make a better decision of what to do next.
In the special case that there is no active lock and the handoff bit
is set, optimistic spinning has to be stopped.
Signed-off-by: Waiman Long <longman@redhat.com>
---
kernel/locking/rwsem-xadd.c | 40 ++++++++++++++++++++++++++++++-------
kernel/locking/rwsem.h | 5 +++++
2 files changed, 38 insertions(+), 7 deletions(-)
diff --git a/kernel/locking/rwsem-xadd.c b/kernel/locking/rwsem-xadd.c
index 4f036bda9063..35891c53338b 100644
--- a/kernel/locking/rwsem-xadd.c
+++ b/kernel/locking/rwsem-xadd.c
@@ -281,14 +281,30 @@ static inline bool rwsem_can_spin_on_owner(struct rw_semaphore *sem)
}
/*
- * Return true only if we can still spin on the owner field of the rwsem.
+ * Return the folowing 4 values depending on the lock owner state.
+ * OWNER_NULL : owner is currently NULL
+ * OWNER_WRITER: when owner changes and is a writer
+ * OWNER_READER: when owner changes and the new owner may be a reader.
+ * OWNER_NONSPINNABLE:
+ * when optimistic spinning has to stop because either the
+ * owner stops running, is unknown, or its timeslice has
+ * been used up.
*/
-static noinline bool rwsem_spin_on_owner(struct rw_semaphore *sem)
+enum owner_state {
+ OWNER_NULL = 1 << 0,
+ OWNER_WRITER = 1 << 1,
+ OWNER_READER = 1 << 2,
+ OWNER_NONSPINNABLE = 1 << 3,
+};
+#define OWNER_SPINNABLE (OWNER_NULL | OWNER_WRITER)
+
+static noinline enum owner_state rwsem_spin_on_owner(struct rw_semaphore *sem)
{
struct task_struct *owner = READ_ONCE(sem->owner);
+ long count;
if (!is_rwsem_owner_spinnable(owner))
- return false;
+ return OWNER_NONSPINNABLE;
rcu_read_lock();
while (owner && (READ_ONCE(sem->owner) == owner)) {
@@ -306,7 +322,7 @@ static noinline bool rwsem_spin_on_owner(struct rw_semaphore *sem)
*/
if (need_resched() || !owner_on_cpu(owner)) {
rcu_read_unlock();
- return false;
+ return OWNER_NONSPINNABLE;
}
cpu_relax();
@@ -315,9 +331,19 @@ static noinline bool rwsem_spin_on_owner(struct rw_semaphore *sem)
/*
* If there is a new owner or the owner is not set, we continue
- * spinning.
+ * spinning except when here is no active locks and the handoff bit
+ * is set. In this case, we have to stop spinning.
*/
- return is_rwsem_owner_spinnable(READ_ONCE(sem->owner));
+ owner = READ_ONCE(sem->owner);
+ if (!is_rwsem_owner_spinnable(owner))
+ return OWNER_NONSPINNABLE;
+ if (owner && !is_rwsem_owner_reader(owner))
+ return OWNER_WRITER;
+
+ count = atomic_long_read(&sem->count);
+ if (RWSEM_COUNT_HANDOFF(count) && !RWSEM_COUNT_LOCKED(count))
+ return OWNER_NONSPINNABLE;
+ return !owner ? OWNER_NULL : OWNER_READER;
}
static bool rwsem_optimistic_spin(struct rw_semaphore *sem)
@@ -340,7 +366,7 @@ static bool rwsem_optimistic_spin(struct rw_semaphore *sem)
* 2) readers own the lock as we can't determine if they are
* actively running or not.
*/
- while (rwsem_spin_on_owner(sem)) {
+ while (rwsem_spin_on_owner(sem) & OWNER_SPINNABLE) {
/*
* Try to acquire the lock
*/
diff --git a/kernel/locking/rwsem.h b/kernel/locking/rwsem.h
index 2befb5ab1181..3ba235491dc1 100644
--- a/kernel/locking/rwsem.h
+++ b/kernel/locking/rwsem.h
@@ -119,6 +119,11 @@ static inline bool is_rwsem_owner_spinnable(struct task_struct *owner)
return !((unsigned long)owner & RWSEM_ANONYMOUSLY_OWNED);
}
+static inline bool is_rwsem_owner_reader(struct task_struct *owner)
+{
+ return (unsigned long)owner & RWSEM_READER_OWNED;
+}
+
/*
* Return true if rwsem is owned by an anonymous writer or readers.
*/
--
2.18.1
next prev parent reply other threads:[~2019-04-05 19:22 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-04-05 19:21 [PATCH-tip v2 00/12] locking/rwsem: Rwsem rearchitecture part 2 Waiman Long
2019-04-05 19:21 ` [PATCH-tip v2 01/12] locking/rwsem: Implement a new locking scheme Waiman Long
2019-04-05 19:21 ` [PATCH-tip v2 02/12] locking/rwsem: Implement lock handoff to prevent lock starvation Waiman Long
2019-04-10 15:07 ` Peter Zijlstra
2019-04-10 15:28 ` Waiman Long
2019-04-10 15:10 ` Peter Zijlstra
2019-04-10 15:29 ` Waiman Long
2019-04-10 18:44 ` Peter Zijlstra
2019-04-11 2:25 ` Waiman Long
2019-04-11 7:16 ` Peter Zijlstra
2019-04-05 19:21 ` [PATCH-tip v2 03/12] locking/rwsem: Remove rwsem_wake() wakeup optimization Waiman Long
2019-04-10 18:38 ` Davidlohr Bueso
2019-04-05 19:21 ` Waiman Long [this message]
2019-04-05 19:21 ` [PATCH-tip v2 05/12] locking/rwsem: Ensure an RT task will not spin on reader Waiman Long
2019-04-05 19:21 ` [PATCH-tip v2 06/12] locking/rwsem: Wake up almost all readers in wait queue Waiman Long
2019-04-10 16:50 ` Davidlohr Bueso
2019-04-10 17:08 ` Waiman Long
2019-04-10 17:22 ` Davidlohr Bueso
2019-04-10 17:31 ` Davidlohr Bueso
2019-04-10 17:54 ` Waiman Long
2019-04-10 17:53 ` Waiman Long
2019-04-05 19:21 ` [PATCH-tip v2 07/12] locking/rwsem: Enable readers spinning on writer Waiman Long
2019-04-05 19:21 ` [PATCH-tip v2 08/12] locking/rwsem: Enable time-based spinning on reader-owned rwsem Waiman Long
2019-04-05 19:21 ` [PATCH-tip v2 09/12] locking/rwsem: Add more rwsem owner access helpers Waiman Long
2019-04-05 19:21 ` [PATCH-tip v2 10/12] locking/rwsem: Guard against making count negative Waiman Long
2019-04-05 19:21 ` [PATCH-tip v2 11/12] locking/rwsem: Merge owner into count on x86-64 Waiman Long
2019-04-05 19:21 ` [PATCH-tip v2 12/12] locking/rwsem: Remove redundant computation of writer lock word Waiman Long
2019-04-05 23:27 ` [PATCH-tip v2 00/12] locking/rwsem: Rwsem rearchitecture part 2 Linus Torvalds
2019-04-10 10:00 ` Ingo Molnar
2019-04-10 12:38 ` 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=20190405192115.17416-5-longman@redhat.com \
--to=longman@redhat.com \
--cc=dave@stgolabs.net \
--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.