linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
From: Nicholas Piggin <npiggin@gmail.com>
To: linuxppc-dev@lists.ozlabs.org
Cc: Jordan Niethe <jniethe5@gmail.com>,
	Laurent Dufour <laurent.dufour@fr.ibm.com>,
	Nicholas Piggin <npiggin@gmail.com>
Subject: [RFC PATCH 3/4] powerpc/qspinlock: Remove !maybe_waiters special case queue head locking
Date: Tue, 15 Nov 2022 02:11:18 +1000	[thread overview]
Message-ID: <20221114161119.2883620-4-npiggin@gmail.com> (raw)
In-Reply-To: <20221114161119.2883620-1-npiggin@gmail.com>

With the update primitive that clears the tail if it matches, and is
tolerant of other queueing activity on the lock, there is no longer a
significant reason to keep the large !maybe_stealers special case, so
remove it.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
 arch/powerpc/lib/qspinlock.c | 124 +++++++++++++++--------------------
 1 file changed, 53 insertions(+), 71 deletions(-)

diff --git a/arch/powerpc/lib/qspinlock.c b/arch/powerpc/lib/qspinlock.c
index 79793b3209ea..457e748b0078 100644
--- a/arch/powerpc/lib/qspinlock.c
+++ b/arch/powerpc/lib/qspinlock.c
@@ -523,7 +523,11 @@ static __always_inline void queued_spin_lock_mcs_queue(struct qspinlock *lock, b
 	struct qnode *next, *node;
 	u32 val, old, tail;
 	bool seen_preempted = false;
+	bool sleepy = false;
+	bool mustq = false;
 	int idx;
+	int set_yield_cpu = -1;
+	int iters = 0;
 
 	BUILD_BUG_ON(CONFIG_NR_CPUS >= (1U << _Q_TAIL_CPU_BITS));
 
@@ -577,90 +581,68 @@ static __always_inline void queued_spin_lock_mcs_queue(struct qspinlock *lock, b
 		smp_rmb(); /* acquire barrier for the mcs lock */
 	}
 
-	if (!maybe_stealers) {
-		int set_yield_cpu = -1;
-
-		/* We're at the head of the waitqueue, wait for the lock. */
-		spin_begin();
-		for (;;) {
-			val = READ_ONCE(lock->val);
-			if (!(val & _Q_LOCKED_VAL))
-				break;
-
-			propagate_yield_cpu(node, val, &set_yield_cpu, paravirt);
-			if (yield_head_to_locked_owner(lock, val, paravirt))
-				seen_preempted = true;
-		}
-		spin_end();
-
-		/* If we're the last queued, must clean up the tail. */
-		old = trylock_clear_my_tail(lock, tail);
-		BUG_ON(old & _Q_LOCKED_VAL);
-		if ((old & _Q_TAIL_CPU_MASK) == tail)
-			goto release;
-
-	} else {
-		int set_yield_cpu = -1;
-		int iters = 0;
-		bool sleepy = false;
-		bool mustq = false;
+	/* We're at the head of the waitqueue, wait for the lock. */
+again:
+	spin_begin();
+	for (;;) {
 		bool preempted;
 
-again:
-		/* We're at the head of the waitqueue, wait for the lock. */
-		spin_begin();
-		for (;;) {
-			val = READ_ONCE(lock->val);
-			if (!(val & _Q_LOCKED_VAL))
-				break;
-
-			if (paravirt && pv_sleepy_lock) {
-				if (!sleepy) {
-					if (val & _Q_SLEEPY_VAL) {
-						seen_sleepy_lock();
-						sleepy = true;
-					} else if (recently_sleepy()) {
-						sleepy = true;
-					}
-				}
-				if (pv_sleepy_lock_sticky && seen_preempted &&
-						!(val & _Q_SLEEPY_VAL)) {
-					if (try_set_sleepy(lock, val))
-						val |= _Q_SLEEPY_VAL;
+		val = READ_ONCE(lock->val);
+		if (!(val & _Q_LOCKED_VAL))
+			break;
+
+		if (paravirt && pv_sleepy_lock && maybe_stealers) {
+			if (!sleepy) {
+				if (val & _Q_SLEEPY_VAL) {
+					seen_sleepy_lock();
+					sleepy = true;
+				} else if (recently_sleepy()) {
+					sleepy = true;
 				}
 			}
+			if (pv_sleepy_lock_sticky && seen_preempted &&
+					!(val & _Q_SLEEPY_VAL)) {
+				if (try_set_sleepy(lock, val))
+					val |= _Q_SLEEPY_VAL;
+			}
+		}
 
-			propagate_yield_cpu(node, val, &set_yield_cpu, paravirt);
-			preempted = yield_head_to_locked_owner(lock, val, paravirt);
-			if (preempted)
-				seen_preempted = true;
+		propagate_yield_cpu(node, val, &set_yield_cpu, paravirt);
+		preempted = yield_head_to_locked_owner(lock, val, paravirt);
+		if (!maybe_stealers)
+			continue;
+
+		if (preempted)
+			seen_preempted = true;
 
-			if (paravirt && preempted) {
-				sleepy = true;
+		if (paravirt && preempted) {
+			sleepy = true;
 
-				if (!pv_spin_on_preempted_owner)
-					iters++;
-			} else {
+			if (!pv_spin_on_preempted_owner)
 				iters++;
-			}
+		} else {
+			iters++;
+		}
 
-			if (!mustq && iters >= get_head_spins(paravirt, sleepy)) {
-				mustq = true;
-				set_mustq(lock);
-				val |= _Q_MUST_Q_VAL;
-			}
+		if (!mustq && iters >= get_head_spins(paravirt, sleepy)) {
+			mustq = true;
+			set_mustq(lock);
+			val |= _Q_MUST_Q_VAL;
 		}
-		spin_end();
+	}
+	spin_end();
 
-		/* If we're the last queued, must clean up the tail. */
-		old = trylock_clear_my_tail(lock, tail);
-		if (unlikely(old & _Q_LOCKED_VAL))
-			goto again;
-		if ((old & _Q_TAIL_CPU_MASK) == tail)
-			goto release;
+	/* If we're the last queued, must clean up the tail. */
+	old = trylock_clear_my_tail(lock, tail);
+	if (unlikely(old & _Q_LOCKED_VAL)) {
+		BUG_ON(!maybe_stealers);
+		goto again; /* Can only be true if maybe_stealers. */
 	}
 
-	/* contended path; must wait for next != NULL (MCS protocol) */
+	if ((old & _Q_TAIL_CPU_MASK) == tail)
+		goto release; /* We were the tail, no next. */
+
+	/* There is a next, must wait for node->next != NULL (MCS protocol) */
 	next = READ_ONCE(node->next);
 	if (!next) {
 		spin_begin();
-- 
2.37.2


  parent reply	other threads:[~2022-11-14 16:15 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-14 16:11 [RFC PATCH 0/4] powerpc/qspinlock: make slowpath accesses more efficient Nicholas Piggin
2022-11-14 16:11 ` [RFC PATCH 1/4] powerpc/qspinlock: Avoid cmpxchg pattern in lock stealing Nicholas Piggin
2022-11-14 16:11 ` [RFC PATCH 2/4] powerpc/qspinlock: Avoid cmpxchg style patterns in queue head locking Nicholas Piggin
2022-11-14 16:11 ` Nicholas Piggin [this message]
2022-11-14 16:11 ` [RFC PATCH 4/4] powerpc/qspinlock: add compile-time tuning adjustments Nicholas Piggin

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=20221114161119.2883620-4-npiggin@gmail.com \
    --to=npiggin@gmail.com \
    --cc=jniethe5@gmail.com \
    --cc=laurent.dufour@fr.ibm.com \
    --cc=linuxppc-dev@lists.ozlabs.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;
as well as URLs for NNTP newsgroup(s).