linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Thomas Gleixner <tglx@linutronix.de>
To: LKML <linux-kernel@vger.kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>,
	Ingo Molnar <mingo@kernel.org>,
	Juri Lelli <juri.lelli@redhat.com>,
	Steven Rostedt <rostedt@goodmis.org>,
	Daniel Bristot de Oliveira <bristot@redhat.com>,
	Will Deacon <will@kernel.org>, Waiman Long <longman@redhat.com>,
	Boqun Feng <boqun.feng@gmail.com>,
	Sebastian Andrzej Siewior <bigeasy@linutronix.de>,
	Davidlohr Bueso <dave@stgolabs.net>,
	Mike Galbraith <efault@gmx.de>
Subject: [patch V3 64/64] locking/rtmutex: Add adaptive spinwait mechanism
Date: Thu, 05 Aug 2021 17:14:04 +0200	[thread overview]
Message-ID: <20210805153956.507589092@linutronix.de> (raw)
In-Reply-To: 20210805151300.330412127@linutronix.de

From: Steven Rostedt <rostedt@goodmis.org>

Going to sleep when locks are contended can be quite inefficient when the
contention time is short and the lock owner is running on a different CPU.

The MCS mechanism cannot be used because MCS is strictly FIFO ordered while
for rtmutex based locks the waiter ordering is priority based.

Provide a simple adaptive spinwait mechanism which currently restricts the
spinning to the top priority waiter.

[ tglx: Provide a contemporary changelog ]

Originally-by: Gregory Haskins <ghaskins@novell.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
V3: Fold the extension for regular sleeping locks and add the missing spin
    wait checks (PeterZ)
---
 kernel/locking/rtmutex.c |   59 +++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 57 insertions(+), 2 deletions(-)
---
--- a/kernel/locking/rtmutex.c
+++ b/kernel/locking/rtmutex.c
@@ -8,6 +8,11 @@
  *  Copyright (C) 2005-2006 Timesys Corp., Thomas Gleixner <tglx@timesys.com>
  *  Copyright (C) 2005 Kihon Technologies Inc., Steven Rostedt
  *  Copyright (C) 2006 Esben Nielsen
+ * Adaptive Spinlocks:
+ *  Copyright (C) 2008 Novell, Inc., Gregory Haskins, Sven Dietrich,
+ *				     and Peter Morreale,
+ * Adaptive Spinlocks simplification:
+ *  Copyright (C) 2008 Red Hat, Inc., Steven Rostedt <srostedt@redhat.com>
  *
  *  See Documentation/locking/rt-mutex-design.rst for details.
  */
@@ -1278,6 +1283,44 @@ static __always_inline void __rt_mutex_u
 	rt_mutex_slowunlock(lock);
 }
 
+#ifdef CONFIG_SMP
+/*
+ * Note that owner is a speculative pointer and dereferencing relies
+ * on rcu_read_lock() and the check against the lock owner.
+ */
+static bool rtmutex_adaptive_spinwait(struct rt_mutex_base *lock,
+				     struct task_struct *owner)
+{
+	bool res = true;
+
+	rcu_read_lock();
+	for (;;) {
+		/* Owner changed. Trylock again */
+		if (owner != rt_mutex_owner(lock))
+			break;
+		/*
+		 * Ensure that owner->on_cpu is dereferenced _after_
+		 * checking the above to be valid.
+		 */
+		barrier();
+		if (!owner->on_cpu || need_resched() ||
+		    vcpu_is_preempted(task_cpu(owner))) {
+			res = false;
+			break;
+		}
+		cpu_relax();
+	}
+	rcu_read_unlock();
+	return res;
+}
+#else
+static bool rtmutex_adaptive_spinwait(struct rt_mutex_base *lock,
+				     struct task_struct *owner)
+{
+	return false;
+}
+#endif
+
 #ifdef RT_MUTEX_BUILD_MUTEX
 /*
  * Functions required for:
@@ -1362,6 +1405,7 @@ static int __sched rt_mutex_slowlock_blo
 					   struct rt_mutex_waiter *waiter)
 {
 	struct rt_mutex *rtm = container_of(lock, struct rt_mutex, rtmutex);
+	struct task_struct *owner;
 	int ret = 0;
 
 	for (;;) {
@@ -1384,9 +1428,14 @@ static int __sched rt_mutex_slowlock_blo
 				break;
 		}
 
+		if (waiter == rt_mutex_top_waiter(lock))
+			owner = rt_mutex_owner(lock);
+		else
+			owner = NULL;
 		raw_spin_unlock_irq(&lock->wait_lock);
 
-		schedule();
+		if (!owner || !rtmutex_adaptive_spinwait(lock, owner))
+			schedule();
 
 		raw_spin_lock_irq(&lock->wait_lock);
 		set_current_state(state);
@@ -1542,6 +1591,7 @@ static __always_inline int __rt_mutex_lo
 static void __sched rtlock_slowlock_locked(struct rt_mutex_base *lock)
 {
 	struct rt_mutex_waiter waiter;
+	struct task_struct *owner;
 
 	lockdep_assert_held(&lock->wait_lock);
 
@@ -1560,9 +1610,14 @@ static void __sched rtlock_slowlock_lock
 		if (try_to_take_rt_mutex(lock, current, &waiter))
 			break;
 
+		if (&waiter == rt_mutex_top_waiter(lock))
+			owner = rt_mutex_owner(lock);
+		else
+			owner = NULL;
 		raw_spin_unlock_irq(&lock->wait_lock);
 
-		schedule_rtlock();
+		if (!owner || !rtmutex_adaptive_spinwait(lock, owner))
+			schedule_rtlock();
 
 		raw_spin_lock_irq(&lock->wait_lock);
 		set_current_state(TASK_RTLOCK_WAIT);


  parent reply	other threads:[~2021-08-05 15:46 UTC|newest]

Thread overview: 79+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-08-05 15:13 [patch V3 00/64] locking, sched: The PREEMPT-RT locking infrastructure Thomas Gleixner
2021-08-05 15:13 ` [patch V3 01/64] sched: Split out the wakeup state check Thomas Gleixner
2021-08-05 15:13 ` [patch V3 02/64] sched: Introduce TASK_RTLOCK_WAIT Thomas Gleixner
2021-08-05 15:13 ` [patch V3 03/64] sched: Reorganize current::__state helpers Thomas Gleixner
2021-08-05 15:13 ` [patch V3 04/64] sched: Prepare for RT sleeping spin/rwlocks Thomas Gleixner
2021-08-05 15:13 ` [patch V3 05/64] sched: Rework the __schedule() preempt argument Thomas Gleixner
2021-08-05 15:13 ` [patch V3 06/64] sched: Provide schedule point for RT locks Thomas Gleixner
2021-08-05 15:13 ` [patch V3 07/64] sched/wake_q: Provide WAKE_Q_HEAD_INITIALIZER Thomas Gleixner
2021-08-05 15:13 ` [patch V3 08/64] media/atomisp: Use lockdep instead of *mutex_is_locked() Thomas Gleixner
2021-08-05 15:13 ` [patch V3 09/64] rtmutex: Remove rt_mutex_is_locked() Thomas Gleixner
2021-08-05 15:13 ` [patch V3 10/64] rtmutex: Convert macros to inlines Thomas Gleixner
2021-08-05 15:13 ` [patch V3 11/64] rtmutex: Switch to try_cmpxchg() Thomas Gleixner
2021-08-05 15:13 ` [patch V3 12/64] rtmutex: Split API and implementation Thomas Gleixner
2021-08-05 15:13 ` [patch V3 13/64] rtmutex: Split out the inner parts of struct rtmutex Thomas Gleixner
2021-08-05 15:13 ` [patch V3 14/64] locking/rtmutex: Provide rt_mutex_slowlock_locked() Thomas Gleixner
2021-08-05 15:13 ` [patch V3 15/64] rtmutex: Provide rt_mutex_base_is_locked() Thomas Gleixner
2021-08-08 20:41   ` Davidlohr Bueso
2021-08-09 10:18     ` Thomas Gleixner
2021-08-05 15:13 ` [patch V3 16/64] locking: Add base code for RT rw_semaphore and rwlock Thomas Gleixner
2021-08-05 15:13 ` [patch V3 17/64] locking/rwsem: Add rtmutex based R/W semaphore implementation Thomas Gleixner
2021-08-05 15:13 ` [patch V3 18/64] locking/rtmutex: Add wake_state to rt_mutex_waiter Thomas Gleixner
2021-08-05 15:13 ` [patch V3 19/64] locking/rtmutex: Provide rt_wake_q and helpers Thomas Gleixner
2021-08-05 15:13 ` [patch V3 20/64] locking/rtmutex: Use rt_mutex_wake_q_head Thomas Gleixner
2021-08-05 15:13 ` [patch V3 21/64] locking/rtmutex: Prepare RT rt_mutex_wake_q for RT locks Thomas Gleixner
2021-08-05 15:13 ` [patch V3 22/64] locking/rtmutex: Guard regular sleeping locks specific functions Thomas Gleixner
2021-08-05 15:13 ` [patch V3 23/64] locking/spinlock: Split the lock types header Thomas Gleixner
2021-08-05 15:13 ` [patch V3 24/64] locking/rtmutex: Prevent future include recursion hell Thomas Gleixner
2021-08-05 15:13 ` [patch V3 25/64] locking/lockdep: Reduce includes in debug_locks.h Thomas Gleixner
2021-08-05 15:13 ` [patch V3 26/64] rbtree: Split out the rbtree type definitions Thomas Gleixner
2021-08-05 15:13 ` [patch V3 27/64] locking/rtmutex: Include only rbtree types Thomas Gleixner
2021-08-05 15:13 ` [patch V3 28/64] locking/spinlock: Provide RT specific spinlock type Thomas Gleixner
2021-08-05 15:13 ` [patch V3 29/64] locking/spinlock: Provide RT variant header Thomas Gleixner
2021-08-05 15:13 ` [patch V3 30/64] locking/rtmutex: Provide the spin/rwlock core lock function Thomas Gleixner
2021-08-05 15:13 ` [patch V3 31/64] locking/spinlock: Provide RT variant Thomas Gleixner
2021-08-05 15:13 ` [patch V3 32/64] locking/rwlock: " Thomas Gleixner
2021-08-05 15:13 ` [patch V3 33/64] locking/mutex: Consolidate core headers Thomas Gleixner
2021-08-05 15:13 ` [patch V3 34/64] locking/mutex: Move waiter to core header Thomas Gleixner
2021-08-05 15:13 ` [patch V3 35/64] locking/ww_mutex: Move ww_mutex declarations into ww_mutex.h Thomas Gleixner
2021-08-05 15:13 ` [patch V3 36/64] locking/mutex: Make mutex::wait_lock raw Thomas Gleixner
2021-08-05 15:13 ` [patch V3 37/64] locking/ww_mutex: Simplify lockdep annotation Thomas Gleixner
2021-08-05 15:13 ` [patch V3 38/64] locking/ww_mutex: Gather mutex_waiter initialization Thomas Gleixner
2021-08-05 15:13 ` [patch V3 39/64] locking/ww_mutex: Split up ww_mutex_unlock() Thomas Gleixner
2021-08-05 15:13 ` [patch V3 40/64] locking/ww_mutex: Split W/W implementation logic Thomas Gleixner
2021-08-05 15:13 ` [patch V3 41/64] locking/ww_mutex: Remove __sched annotation Thomas Gleixner
2021-08-05 15:13 ` [patch V3 42/64] locking/ww_mutex: Abstract waiter iteration Thomas Gleixner
2021-08-05 15:13 ` [patch V3 43/64] locking/ww_mutex: Abstract waiter enqueueing Thomas Gleixner
2021-08-05 15:13 ` [patch V3 44/64] locking/ww_mutex: Abstract mutex accessors Thomas Gleixner
2021-08-05 15:13 ` [patch V3 45/64] locking/ww_mutex: Abstract mutex types Thomas Gleixner
2021-08-05 15:13 ` [patch V3 46/64] locking/ww_mutex: Abstract internal lock access Thomas Gleixner
2021-08-05 15:13 ` [patch V3 47/64] locking/ww_mutex: Implement rt_mutex accessors Thomas Gleixner
2021-08-05 15:13 ` [patch V3 48/64] locking/ww_mutex: Add RT priority to W/W order Thomas Gleixner
2021-08-06 10:48   ` Peter Zijlstra
2021-08-06 11:50     ` Thomas Gleixner
2021-08-05 15:13 ` [patch V3 49/64] locking/ww_mutex: Add rt_mutex based lock type and accessors Thomas Gleixner
2021-08-05 15:13 ` [patch V3 50/64] locking/rtmutex: Extend the rtmutex core to support ww_mutex Thomas Gleixner
2021-08-06 11:00   ` Peter Zijlstra
2021-08-06 11:19     ` Thomas Gleixner
2021-08-06 13:48     ` Peter Zijlstra
2021-08-07 20:07       ` Thomas Gleixner
2021-08-05 15:13 ` [patch V3 51/64] locking/ww_mutex: Implement rtmutex based ww_mutex API functions Thomas Gleixner
2021-08-05 15:13 ` [patch V3 52/64] locking/rtmutex: Add mutex variant for RT Thomas Gleixner
2021-08-05 15:13 ` [patch V3 53/64] lib/test_lockup: Adapt to changed variables Thomas Gleixner
2021-08-05 15:13 ` [patch V3 54/64] futex: Validate waiter correctly in futex_proxy_trylock_atomic() Thomas Gleixner
2021-08-05 15:13 ` [patch V3 55/64] futex: Cleanup stale comments Thomas Gleixner
2021-08-05 15:13 ` [patch V3 56/64] futex: Correct the number of requeued waiters for PI Thomas Gleixner
2021-08-08 17:05   ` Davidlohr Bueso
2021-08-09  8:18     ` Thomas Gleixner
2021-08-09 10:52       ` Thomas Gleixner
2021-08-05 15:13 ` [patch V3 57/64] futex: Restructure futex_requeue() Thomas Gleixner
2021-08-05 15:13 ` [patch V3 58/64] futex: Clarify comment in futex_requeue() Thomas Gleixner
2021-08-08 18:43   ` Davidlohr Bueso
2021-08-09  8:18     ` Thomas Gleixner
2021-08-05 15:13 ` [patch V3 59/64] futex: Simplify handle_early_requeue_pi_wakeup() Thomas Gleixner
2021-08-05 15:14 ` [patch V3 60/64] futex: Prevent requeue_pi() lock nesting issue on RT Thomas Gleixner
2021-08-05 15:14 ` [patch V3 61/64] rtmutex: Prevent lockdep false positive with PI futexes Thomas Gleixner
2021-08-05 15:14 ` [patch V3 62/64] preempt: Adjust PREEMPT_LOCK_OFFSET for RT Thomas Gleixner
2021-08-05 15:14 ` [patch V3 63/64] locking/rtmutex: Implement equal priority lock stealing Thomas Gleixner
2021-08-05 15:14 ` Thomas Gleixner [this message]
2021-08-09 20:28   ` [patch V3 64/64] locking/rtmutex: Add adaptive spinwait mechanism Davidlohr Bueso

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=20210805153956.507589092@linutronix.de \
    --to=tglx@linutronix.de \
    --cc=bigeasy@linutronix.de \
    --cc=boqun.feng@gmail.com \
    --cc=bristot@redhat.com \
    --cc=dave@stgolabs.net \
    --cc=efault@gmx.de \
    --cc=juri.lelli@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=longman@redhat.com \
    --cc=mingo@kernel.org \
    --cc=peterz@infradead.org \
    --cc=rostedt@goodmis.org \
    --cc=will@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;
as well as URLs for NNTP newsgroup(s).