From: Waiman Long <Waiman.Long@hp.com>
To: Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@redhat.com>,
Thomas Gleixner <tglx@linutronix.de>,
"H. Peter Anvin" <hpa@zytor.com>
Cc: x86@kernel.org, linux-kernel@vger.kernel.org,
Scott J Norton <scott.norton@hp.com>,
Douglas Hatch <doug.hatch@hp.com>,
Davidlohr Bueso <dave@stgolabs.net>,
Waiman Long <Waiman.Long@hp.com>
Subject: [PATCH v3 4/7] locking/pvqspinlock: Enable deferment of vCPU kicking to unlock call
Date: Wed, 22 Jul 2015 16:12:39 -0400 [thread overview]
Message-ID: <1437595962-21472-5-git-send-email-Waiman.Long@hp.com> (raw)
In-Reply-To: <1437595962-21472-1-git-send-email-Waiman.Long@hp.com>
Most of the vCPU kickings are done on the locking side where the new
lock holder wake up the queue head vCPU to spin on the lock. However,
there are situations where it may be advantageous to defer the vCPU
kicking to when the lock holder releases the lock.
This patch enables the deferment of vCPU kicking to the unlock function
by adding a new vCPU state (vcpu_hashed) to marks the fact that
1) _Q_SLOW_VAL is set in the lock, and
2) the pv_node address is stored in the hash table
This enablement patch, by itself, should not change the performance
of the pvqspinlock code. Actual deferment vCPU kicks will be added
in a later patch.
Signed-off-by: Waiman Long <Waiman.Long@hp.com>
---
kernel/locking/qspinlock.c | 6 +++---
kernel/locking/qspinlock_paravirt.h | 34 ++++++++++++++++++++++++----------
2 files changed, 27 insertions(+), 13 deletions(-)
diff --git a/kernel/locking/qspinlock.c b/kernel/locking/qspinlock.c
index 6518ee9..94fdd27 100644
--- a/kernel/locking/qspinlock.c
+++ b/kernel/locking/qspinlock.c
@@ -259,8 +259,8 @@ static __always_inline void set_locked(struct qspinlock *lock)
static __always_inline void __pv_init_node(struct mcs_spinlock *node) { }
static __always_inline void __pv_wait_node(struct mcs_spinlock *node) { }
-static __always_inline void __pv_kick_node(struct mcs_spinlock *node) { }
-
+static __always_inline void __pv_kick_node(struct qspinlock *lock,
+ struct mcs_spinlock *node) { }
static __always_inline void __pv_wait_head(struct qspinlock *lock,
struct mcs_spinlock *node) { }
@@ -464,7 +464,7 @@ queue:
cpu_relax();
arch_mcs_spin_unlock_contended(&next->locked);
- pv_kick_node(next);
+ pv_kick_node(lock, next);
release:
/*
diff --git a/kernel/locking/qspinlock_paravirt.h b/kernel/locking/qspinlock_paravirt.h
index db8d08b..a4986c6 100644
--- a/kernel/locking/qspinlock_paravirt.h
+++ b/kernel/locking/qspinlock_paravirt.h
@@ -33,6 +33,7 @@
enum vcpu_state {
vcpu_running = 0,
vcpu_halted,
+ vcpu_hashed, /* vcpu_halted + node stored in hash table */
};
struct pv_node {
@@ -404,13 +405,17 @@ static void pv_wait_node(struct mcs_spinlock *node)
pv_wait(&pn->state, vcpu_halted);
}
+ if (READ_ONCE(node->locked))
+ break;
+
/*
- * Reset the vCPU state to avoid unncessary CPU kicking
+ * Reset the vCPU state to running to avoid unncessary CPU
+ * kicking unless vcpu_hashed had already been set. In this
+ * case, node->locked should have just been set, and we
+ * aren't going to set state to vcpu_halted again.
*/
- WRITE_ONCE(pn->state, vcpu_running);
+ cmpxchg(&pn->state, vcpu_halted, vcpu_running);
- if (READ_ONCE(node->locked))
- break;
/*
* If the locked flag is still not set after wakeup, it is a
* spurious wakeup and the vCPU should wait again. However,
@@ -429,12 +434,16 @@ static void pv_wait_node(struct mcs_spinlock *node)
/*
* Called after setting next->locked = 1, used to wake those stuck in
- * pv_wait_node().
+ * pv_wait_node(). Alternatively, it can also defer the kicking to the
+ * unlock function.
*/
-static void pv_kick_node(struct mcs_spinlock *node)
+static void pv_kick_node(struct qspinlock *lock, struct mcs_spinlock *node)
{
struct pv_node *pn = (struct pv_node *)node;
+ if (xchg(&pn->state, vcpu_running) != vcpu_halted)
+ return;
+
/*
* Note that because node->locked is already set, this actual
* mcs_spinlock entry could be re-used already.
@@ -444,10 +453,8 @@ static void pv_kick_node(struct mcs_spinlock *node)
*
* See the comment in pv_wait_node().
*/
- if (xchg(&pn->state, vcpu_running) == vcpu_halted) {
- pvstat_inc(pvstat_lock_kick);
- pv_kick(pn->cpu);
- }
+ pvstat_inc(pvstat_lock_kick);
+ pv_kick(pn->cpu);
}
/*
@@ -469,6 +476,13 @@ static void pv_wait_head(struct qspinlock *lock, struct mcs_spinlock *node)
cpu_relax();
}
+ if (!lp && (xchg(&pn->state, vcpu_hashed) == vcpu_hashed))
+ /*
+ * The hashed table & _Q_SLOW_VAL had been filled
+ * by the lock holder.
+ */
+ lp = (struct qspinlock **)-1;
+
if (!lp) { /* ONCE */
lp = pv_hash(lock, pn);
/*
--
1.7.1
next prev parent reply other threads:[~2015-07-22 20:14 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-07-22 20:12 [PATCH v3 0/7] locking/qspinlock: Enhance pvqspinlock performance Waiman Long
2015-07-22 20:12 ` [PATCH v3 1/7] locking/pvqspinlock: Unconditional PV kick with _Q_SLOW_VAL Waiman Long
2015-07-25 22:31 ` Davidlohr Bueso
2015-07-27 1:46 ` Davidlohr Bueso
2015-07-27 17:50 ` Waiman Long
2015-07-27 18:41 ` Davidlohr Bueso
2015-07-31 8:39 ` Peter Zijlstra
2015-07-31 17:01 ` Waiman Long
2015-07-22 20:12 ` [PATCH v3 2/7] locking/pvqspinlock: Add pending bit support Waiman Long
2015-07-26 23:09 ` Davidlohr Bueso
2015-07-27 17:11 ` Waiman Long
2015-07-26 23:48 ` Davidlohr Bueso
2015-07-27 0:56 ` Davidlohr Bueso
2015-07-27 17:30 ` Waiman Long
2015-07-27 19:39 ` Davidlohr Bueso
2015-07-29 20:49 ` Waiman Long
2015-07-27 20:08 ` Davidlohr Bueso
2015-07-22 20:12 ` [PATCH v3 3/7] locking/pvqspinlock: Collect slowpath lock statistics Waiman Long
2015-07-27 1:14 ` Davidlohr Bueso
2015-07-27 17:33 ` Waiman Long
2015-07-22 20:12 ` Waiman Long [this message]
2015-07-22 20:12 ` [PATCH v3 5/7] locking/pvqspinlock: Allow vCPUs kick-ahead Waiman Long
2015-07-22 20:12 ` [PATCH v3 6/7] locking/pvqspinlock: Queue node adaptive spinning Waiman Long
2015-07-22 20:12 ` [PATCH v3 7/7] locking/pvqspinlock, x86: Optimize PV unlock code path Waiman Long
2015-07-27 1:18 ` [PATCH v3 0/7] locking/qspinlock: Enhance pvqspinlock performance Davidlohr Bueso
2015-07-27 17:36 ` 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=1437595962-21472-5-git-send-email-Waiman.Long@hp.com \
--to=waiman.long@hp.com \
--cc=dave@stgolabs.net \
--cc=doug.hatch@hp.com \
--cc=hpa@zytor.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=peterz@infradead.org \
--cc=scott.norton@hp.com \
--cc=tglx@linutronix.de \
--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®