From: Waiman Long <Waiman.Long@hp.com>
To: Ingo Molnar <mingo@kernel.org>, Peter Zijlstra <peterz@infradead.org>
Cc: linux-kernel@vger.kernel.org, Davidlohr Bueso <davidlohr@hp.com>,
Jason Low <jason.low2@hp.com>,
Scott J Norton <scott.norton@hp.com>,
Waiman Long <Waiman.Long@hp.com>
Subject: [PATCH v2 7/7] locking/rwsem: allow waiting writers to go back to spinning
Date: Thu, 7 Aug 2014 18:26:48 -0400 [thread overview]
Message-ID: <1407450408-11679-8-git-send-email-Waiman.Long@hp.com> (raw)
In-Reply-To: <1407450408-11679-1-git-send-email-Waiman.Long@hp.com>
More aggressive use of optimistic spinning and enabling readers to
participate in spinning may make tasks waiting in the queue harder
to get access to the semaphore, especially for writers who need
exclusive access.
This patch enables a waking writer to go back to the optimistic
spinning loop as long as the owner is really running and spinners are
present. This allows waiting writers better access to the semaphore
as well as reduce the size of the waiting queue.
Signed-off-by: Waiman Long <Waiman.Long@hp.com>
---
kernel/locking/rwsem-xadd.c | 55 +++++++++++++++++++++++++++++++++++--------
1 files changed, 45 insertions(+), 10 deletions(-)
diff --git a/kernel/locking/rwsem-xadd.c b/kernel/locking/rwsem-xadd.c
index 16fabe0..20adbe9 100644
--- a/kernel/locking/rwsem-xadd.c
+++ b/kernel/locking/rwsem-xadd.c
@@ -355,10 +355,15 @@ wake_readers:
}
-static inline bool rwsem_can_spin_on_owner(struct rw_semaphore *sem)
+/*
+ * The defval argument controls whether true or false is returned
+ * when the owner field is NULL.
+ */
+static inline bool
+rwsem_can_spin_on_owner(struct rw_semaphore *sem, bool defval)
{
struct task_struct *owner;
- bool on_cpu = true;
+ bool on_cpu = defval;
if (need_resched())
return false;
@@ -431,7 +436,7 @@ static bool rwsem_optimistic_spin(struct rw_semaphore *sem,
int spincnt = 0;
/* sem->wait_lock should not be held when doing optimistic spinning */
- if (!rwsem_can_spin_on_owner(sem))
+ if (!rwsem_can_spin_on_owner(sem, true))
return false;
preempt_disable();
@@ -489,6 +494,12 @@ static bool rwsem_optimistic_spin(struct rw_semaphore *sem,
{
return false;
}
+
+static inline bool
+rwsem_can_spin_on_owner(struct rw_semaphore *sem, bool default)
+{
+ return false;
+}
#endif
/*
@@ -558,12 +569,14 @@ __visible
struct rw_semaphore __sched *rwsem_down_write_failed(struct rw_semaphore *sem)
{
long count;
- bool waiting = true; /* any queued threads before us */
+ bool waiting; /* any queued threads before us */
+ bool respin;
struct rwsem_waiter waiter;
/* undo write bias from down_write operation, stop active locking */
count = rwsem_atomic_update(-RWSEM_ACTIVE_WRITE_BIAS, sem);
+optspin:
/* do optimistic spinning and steal lock if possible */
if (rwsem_optimistic_spin(sem, RWSEM_WAITING_FOR_WRITE))
return sem;
@@ -578,8 +591,7 @@ struct rw_semaphore __sched *rwsem_down_write_failed(struct rw_semaphore *sem)
raw_spin_lock_irq(&sem->wait_lock);
/* account for this before adding a new element to the list */
- if (list_empty(&sem->wait_list))
- waiting = false;
+ waiting = !list_empty(&sem->wait_list);
list_add_tail(&waiter.list, &sem->wait_list);
@@ -600,23 +612,46 @@ struct rw_semaphore __sched *rwsem_down_write_failed(struct rw_semaphore *sem)
/* wait until we successfully acquire the lock */
set_current_state(TASK_UNINTERRUPTIBLE);
- while (true) {
+ respin = false;
+ while (!respin) {
if (rwsem_try_write_lock(count, sem))
break;
raw_spin_unlock_irq(&sem->wait_lock);
- /* Block until there are no active lockers. */
- do {
+ /*
+ * Block until there are no active lockers or optimistic
+ * spinning is possible.
+ */
+ while (true) {
schedule();
set_current_state(TASK_UNINTERRUPTIBLE);
- } while ((count = sem->count) & RWSEM_ACTIVE_MASK);
+ count = ACCESS_ONCE(sem->count);
+ if (!(count & RWSEM_ACTIVE_MASK))
+ break;
+ /*
+ * Go back to optimistic spinning if the lock
+ * owner is really running and there are spinners.
+ * If there is no spinner, the task is already at
+ * the head of the queue or the lock owner (maybe
+ * readers) may not be actually running.
+ */
+ if (rwsem_has_spinner(sem) &&
+ rwsem_can_spin_on_owner(sem, false)) {
+ respin = true;
+ break;
+ }
+ }
raw_spin_lock_irq(&sem->wait_lock);
}
__set_current_state(TASK_RUNNING);
list_del(&waiter.list);
+ if (respin && list_empty(&sem->wait_list))
+ rwsem_atomic_update(-RWSEM_WAITING_BIAS, sem);
raw_spin_unlock_irq(&sem->wait_lock);
+ if (respin)
+ goto optspin;
return sem;
}
--
1.7.1
next prev parent reply other threads:[~2014-08-07 22:27 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-08-07 22:26 [PATCH v2 0/7] locking/rwsem: enable reader opt-spinning & writer respin Waiman Long
2014-08-07 22:26 ` [PATCH v2 1/7] locking/rwsem: check for active writer/spinner before wakeup Waiman Long
2014-08-08 0:45 ` Davidlohr Bueso
2014-08-08 5:39 ` Davidlohr Bueso
2014-08-08 18:30 ` Waiman Long
2014-08-08 19:03 ` Davidlohr Bueso
2014-08-10 21:41 ` Waiman Long
2014-08-10 23:50 ` Davidlohr Bueso
2014-08-11 19:35 ` Waiman Long
2014-08-08 19:50 ` Jason Low
2014-08-08 20:21 ` Davidlohr Bueso
2014-08-08 20:38 ` Jason Low
2014-08-10 21:44 ` Waiman Long
2014-08-07 22:26 ` [PATCH v2 2/7] locking/rwsem: threshold limited spinning for active readers Waiman Long
2014-08-07 22:26 ` [PATCH v2 3/7] locking/rwsem: rwsem_can_spin_on_owner can be called with preemption enabled Waiman Long
2014-08-07 22:26 ` [PATCH v2 4/7] locking/rwsem: more aggressive use of optimistic spinning Waiman Long
2014-08-07 22:26 ` [PATCH v2 5/7] locking/rwsem: move down rwsem_down_read_failed function Waiman Long
2014-08-07 22:26 ` [PATCH v2 6/7] locking/rwsem: enables optimistic spinning for readers Waiman Long
2014-08-07 22:26 ` Waiman Long [this message]
2014-08-07 23:52 ` [PATCH v2 0/7] locking/rwsem: enable reader opt-spinning & writer respin Davidlohr Bueso
2014-08-08 18:16 ` 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=1407450408-11679-8-git-send-email-Waiman.Long@hp.com \
--to=waiman.long@hp.com \
--cc=davidlohr@hp.com \
--cc=jason.low2@hp.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@kernel.org \
--cc=peterz@infradead.org \
--cc=scott.norton@hp.com \
/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®