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 05/12] locking/rwsem: Ensure an RT task will not spin on reader
Date: Thu, 28 Mar 2019 14:10:59 -0400 [thread overview]
Message-ID: <20190328181106.22887-6-longman@redhat.com> (raw)
In-Reply-To: <20190328181106.22887-1-longman@redhat.com>
An RT task can do optimistic spinning only if the lock holder is
actually running. If the state of the lock holder isn't known, there
is a possibility that high priority of the RT task may block forward
progress of the lock holder if it happens to reside on the same CPU.
This will lead to deadlock. So we have to make sure that an RT task
will not spin on a reader-owned rwsem.
When the owner is temporarily set to NULL, it is more tricky to decide
if an RT task should stop spinning as it may be a temporary state
where another writer may have just stolen the lock which then failed
the task's trylock attempt. So one more retry is allowed to make sure
that the lock is not spinnable by an RT task.
When testing on a 8-socket IvyBridge-EX system, the one additional retry
seems to improve locking performance of RT write locking threads under
heavy contentions. The table below shows the locking rates (in kops/s)
with various write locking threads before and after the patch.
Locking threads Pre-patch Post-patch
--------------- --------- -----------
4 2,753 2,608
8 2,529 2,520
16 1,727 1,918
32 1,263 1,956
64 889 1,343
Signed-off-by: Waiman Long <longman@redhat.com>
---
kernel/locking/rwsem-xadd.c | 38 ++++++++++++++++++++++++++++++-------
1 file changed, 31 insertions(+), 7 deletions(-)
diff --git a/kernel/locking/rwsem-xadd.c b/kernel/locking/rwsem-xadd.c
index 35891c53338b..db9ae5fe6d63 100644
--- a/kernel/locking/rwsem-xadd.c
+++ b/kernel/locking/rwsem-xadd.c
@@ -349,6 +349,8 @@ static noinline enum owner_state rwsem_spin_on_owner(struct rw_semaphore *sem)
static bool rwsem_optimistic_spin(struct rw_semaphore *sem)
{
bool taken = false;
+ bool prev_not_writer = false;
+ bool is_rt_task = rt_task(current);
preempt_disable();
@@ -366,7 +368,12 @@ 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) & OWNER_SPINNABLE) {
+ for (;;) {
+ enum owner_state owner_state = rwsem_spin_on_owner(sem);
+
+ if (!(owner_state & OWNER_SPINNABLE))
+ break;
+
/*
* Try to acquire the lock
*/
@@ -376,13 +383,30 @@ static bool rwsem_optimistic_spin(struct rw_semaphore *sem)
}
/*
- * When there's no owner, we might have preempted between the
- * owner acquiring the lock and setting the owner field. If
- * we're an RT task that will live-lock because we won't let
- * the owner complete.
+ * An RT task cannot do optimistic spinning if it cannot
+ * be sure the lock holder is running or live-lock may
+ * happen if the current task and the lock holder happen
+ * to run in the same CPU.
+ *
+ * When there's no owner or is reader-owned, an RT task
+ * will stop spinning if the owner state is not a writer
+ * at the previous iteration of the loop. This allows the
+ * RT task to recheck if the task that steals the lock is
+ * a spinnable writer. If so, it can keeps on spinning.
+ *
+ * If the owner is a writer, the need_resched() check is
+ * done inside rwsem_spin_on_owner(). If the owner is not
+ * a writer, need_resched() check needs to be done here.
*/
- if (!sem->owner && (need_resched() || rt_task(current)))
- break;
+ if (owner_state != OWNER_WRITER) {
+ if (need_resched())
+ break;
+ if (is_rt_task && prev_not_writer)
+ break;
+ prev_not_writer = true;
+ } else {
+ prev_not_writer = false;
+ }
/*
* The cpu_relax() call is a compiler barrier which forces
--
2.18.1
next prev parent reply other threads:[~2019-03-28 18:12 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-03-28 18:10 [PATCH 00/12] locking/rwsem: Rwsem rearchitecture part 2 Waiman Long
2019-03-28 18:10 ` [PATCH 01/12] locking/rwsem: Implement a new locking scheme Waiman Long
2019-03-28 18:10 ` [PATCH 02/12] locking/rwsem: Implement lock handoff to prevent lock starvation Waiman Long
2019-03-28 18:10 ` [PATCH 03/12] locking/rwsem: Remove rwsem_wake() wakeup optimization Waiman Long
2019-03-28 18:10 ` [PATCH 04/12] locking/rwsem: Make rwsem_spin_on_owner() return owner state Waiman Long
2019-03-28 18:10 ` Waiman Long [this message]
2019-03-28 18:11 ` [PATCH 06/12] locking/rwsem: Wake up almost all readers in wait queue Waiman Long
2019-03-28 18:11 ` [PATCH 07/12] locking/rwsem: Enable readers spinning on writer Waiman Long
2019-03-28 18:11 ` [PATCH 08/12] locking/rwsem: Enable count-based spinning on reader Waiman Long
2019-03-28 18:11 ` [PATCH 09/12] locking/rwsem: Add more rwsem owner access helpers Waiman Long
2019-03-28 18:11 ` [PATCH 10/12] locking/rwsem: Merge owner into count on x86-64 Waiman Long
2019-03-28 20:43 ` Linus Torvalds
2019-03-28 18:11 ` [PATCH 11/12] locking/rwsem: Remove redundant computation of writer lock word Waiman Long
2019-03-28 18:11 ` [PATCH 12/12] locking/rwsem: Make MSbit of count as guard bit to fail readlock Waiman Long
2019-03-28 20:47 ` Linus Torvalds
2019-03-28 20:55 ` Waiman Long
2019-03-28 20:56 ` Linus Torvalds
2019-03-28 21:03 ` Waiman Long
2019-04-03 12:59 ` [PATCH 00/12] locking/rwsem: Rwsem rearchitecture part 2 Peter Zijlstra
2019-04-03 16:08 ` 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=20190328181106.22887-6-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®