From: Boqun Feng <boqun.feng@gmail.com>
To: linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org
Cc: Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@redhat.com>, Will Deacon <will@kernel.org>,
Jonathan Corbet <corbet@lwn.net>,
Waiman Long <longman@redhat.com>,
Boqun Feng <boqun.feng@gmail.com>
Subject: [RFC v7 01/19] locking: More accurate annotations for read_lock()
Date: Fri, 7 Aug 2020 15:42:20 +0800 [thread overview]
Message-ID: <20200807074238.1632519-2-boqun.feng@gmail.com> (raw)
In-Reply-To: <20200807074238.1632519-1-boqun.feng@gmail.com>
On the archs using QUEUED_RWLOCKS, read_lock() is not always a recursive
read lock, actually it's only recursive if in_interrupt() is true. So
change the annotation accordingly to catch more deadlocks.
Note we used to treat read_lock() as pure recursive read locks in
lib/locking-seftest.c, and this is useful, especially for the lockdep
development selftest, so we keep this via a variable to force switching
lock annotation for read_lock().
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
---
include/linux/lockdep.h | 23 ++++++++++++++++++++++-
kernel/locking/lockdep.c | 14 ++++++++++++++
lib/locking-selftest.c | 11 +++++++++++
3 files changed, 47 insertions(+), 1 deletion(-)
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
index 8fce5c98a4b0..6b7cb390f19f 100644
--- a/include/linux/lockdep.h
+++ b/include/linux/lockdep.h
@@ -640,6 +640,20 @@ static inline void print_irqtrace_events(struct task_struct *curr)
}
#endif
+/* Variable used to make lockdep treat read_lock() as recursive in selftests */
+#ifdef CONFIG_DEBUG_LOCKING_API_SELFTESTS
+extern unsigned int force_read_lock_recursive;
+#else /* CONFIG_DEBUG_LOCKING_API_SELFTESTS */
+#define force_read_lock_recursive 0
+#endif /* CONFIG_DEBUG_LOCKING_API_SELFTESTS */
+
+#ifdef CONFIG_LOCKDEP
+extern bool read_lock_is_recursive(void);
+#else /* CONFIG_LOCKDEP */
+/* If !LOCKDEP, the value is meaningless */
+#define read_lock_is_recursive() 0
+#endif
+
/*
* For trivial one-depth nesting of a lock-class, the following
* global define can be used. (Subsystems with multiple levels
@@ -661,7 +675,14 @@ static inline void print_irqtrace_events(struct task_struct *curr)
#define spin_release(l, i) lock_release(l, i)
#define rwlock_acquire(l, s, t, i) lock_acquire_exclusive(l, s, t, NULL, i)
-#define rwlock_acquire_read(l, s, t, i) lock_acquire_shared_recursive(l, s, t, NULL, i)
+#define rwlock_acquire_read(l, s, t, i) \
+do { \
+ if (read_lock_is_recursive()) \
+ lock_acquire_shared_recursive(l, s, t, NULL, i); \
+ else \
+ lock_acquire_shared(l, s, t, NULL, i); \
+} while (0)
+
#define rwlock_release(l, i) lock_release(l, i)
#define seqcount_acquire(l, s, t, i) lock_acquire_exclusive(l, s, t, NULL, i)
diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
index 29a8de4c50b9..fbcbb6350ce7 100644
--- a/kernel/locking/lockdep.c
+++ b/kernel/locking/lockdep.c
@@ -4921,6 +4921,20 @@ static bool lockdep_nmi(void)
return true;
}
+/*
+ * read_lock() is recursive if:
+ * 1. We force lockdep think this way in selftests or
+ * 2. The implementation is not queued read/write lock or
+ * 3. The locker is at an in_interrupt() context.
+ */
+bool read_lock_is_recursive(void)
+{
+ return force_read_lock_recursive ||
+ !IS_ENABLED(CONFIG_QUEUED_RWLOCKS) ||
+ in_interrupt();
+}
+EXPORT_SYMBOL_GPL(read_lock_is_recursive);
+
/*
* We are not always called with irqs disabled - do that here,
* and also avoid lockdep recursion:
diff --git a/lib/locking-selftest.c b/lib/locking-selftest.c
index 14f44f59e733..caadc4dd3368 100644
--- a/lib/locking-selftest.c
+++ b/lib/locking-selftest.c
@@ -28,6 +28,7 @@
* Change this to 1 if you want to see the failure printouts:
*/
static unsigned int debug_locks_verbose;
+unsigned int force_read_lock_recursive;
static DEFINE_WD_CLASS(ww_lockdep);
@@ -1978,6 +1979,11 @@ void locking_selftest(void)
return;
}
+ /*
+ * treats read_lock() as recursive read locks for testing purpose
+ */
+ force_read_lock_recursive = 1;
+
/*
* Run the testsuite:
*/
@@ -2073,6 +2079,11 @@ void locking_selftest(void)
ww_tests();
+ force_read_lock_recursive = 0;
+ /*
+ * queued_read_lock() specific test cases can be put here
+ */
+
if (unexpected_testcase_failures) {
printk("-----------------------------------------------------------------\n");
debug_locks = 0;
--
2.28.0
next prev parent reply other threads:[~2020-08-07 7:43 UTC|newest]
Thread overview: 50+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-08-07 7:42 [RFC v7 00/19] lockdep: Support deadlock detection for recursive read locks Boqun Feng
2020-08-07 7:42 ` Boqun Feng [this message]
2020-08-27 7:54 ` [tip: locking/core] locking: More accurate annotations for read_lock() tip-bot2 for Boqun Feng
2020-08-07 7:42 ` [RFC v7 02/19] lockdep/Documention: Recursive read lock detection reasoning Boqun Feng
2020-08-27 7:54 ` [tip: locking/core] " tip-bot2 for Boqun Feng
2020-08-07 7:42 ` [RFC v7 03/19] lockdep: Demagic the return value of BFS Boqun Feng
2020-08-27 7:54 ` [tip: locking/core] " tip-bot2 for Boqun Feng
2020-08-07 7:42 ` [RFC v7 04/19] lockdep: Make __bfs() visit every dependency until a match Boqun Feng
2020-08-27 7:54 ` [tip: locking/core] " tip-bot2 for Boqun Feng
2020-08-07 7:42 ` [RFC v7 05/19] lockdep: Reduce the size of lock_list::distance Boqun Feng
2020-08-27 7:54 ` [tip: locking/core] " tip-bot2 for Boqun Feng
2020-08-07 7:42 ` [RFC v7 06/19] lockdep: Introduce lock_list::dep Boqun Feng
2020-08-27 7:54 ` [tip: locking/core] " tip-bot2 for Boqun Feng
2020-08-07 7:42 ` [RFC v7 07/19] lockdep: Extend __bfs() to work with multiple types of dependencies Boqun Feng
2020-08-27 7:54 ` [tip: locking/core] " tip-bot2 for Boqun Feng
2020-08-07 7:42 ` [RFC v7 08/19] lockdep: Make __bfs(.match) return bool Boqun Feng
2020-08-27 7:54 ` [tip: locking/core] " tip-bot2 for Boqun Feng
2020-08-07 7:42 ` [RFC v7 09/19] lockdep: Support deadlock detection for recursive read locks in check_noncircular() Boqun Feng
2020-08-27 7:54 ` [tip: locking/core] " tip-bot2 for Boqun Feng
2020-08-07 7:42 ` [RFC v7 10/19] lockdep: Adjust check_redundant() for recursive read change Boqun Feng
2020-08-27 7:54 ` [tip: locking/core] " tip-bot2 for Boqun Feng
2020-08-07 7:42 ` [RFC v7 11/19] lockdep: Fix recursive read lock related safe->unsafe detection Boqun Feng
2020-08-27 7:54 ` [tip: locking/core] " tip-bot2 for Boqun Feng
2020-09-15 18:32 ` [RFC v7 11/19] " Qian Cai
2020-09-16 8:10 ` Boqun Feng
2020-09-16 16:14 ` Boqun Feng
2020-09-16 21:11 ` Qian Cai
2020-09-17 1:53 ` Boqun Feng
2020-08-07 7:42 ` [RFC v7 12/19] lockdep: Add recursive read locks into dependency graph Boqun Feng
2020-08-27 7:54 ` [tip: locking/core] " tip-bot2 for Boqun Feng
2020-09-14 18:16 ` [RFC v7 12/19] " Qian Cai
2020-09-14 22:04 ` Qian Cai
2020-08-07 7:42 ` [RFC v7 13/19] lockdep/selftest: Add a R-L/L-W test case specific to chain cache behavior Boqun Feng
2020-08-27 7:54 ` [tip: locking/core] " tip-bot2 for Boqun Feng
2020-08-07 7:42 ` [RFC v7 14/19] lockdep: Take read/write status in consideration when generate chainkey Boqun Feng
2020-08-21 17:41 ` Peter Zijlstra
2020-08-22 2:52 ` boqun.feng
2020-08-27 7:54 ` [tip: locking/core] " tip-bot2 for Boqun Feng
2020-08-07 7:42 ` [RFC v7 15/19] lockdep/selftest: Unleash irq_read_recursion2 and add more Boqun Feng
2020-08-27 7:54 ` [tip: locking/core] " tip-bot2 for Boqun Feng
2020-08-07 7:42 ` [RFC v7 16/19] lockdep/selftest: Add more recursive read related test cases Boqun Feng
2020-08-27 7:54 ` [tip: locking/core] " tip-bot2 for Boqun Feng
2020-08-07 7:42 ` [RFC v7 17/19] Revert "locking/lockdep/selftests: Fix mixed read-write ABBA tests" Boqun Feng
2020-08-27 7:54 ` [tip: locking/core] " tip-bot2 for Boqun Feng
2020-08-07 7:42 ` [RFC v7 18/19] locking/selftest: Add test cases for queued_read_lock() Boqun Feng
2020-08-27 7:54 ` [tip: locking/core] " tip-bot2 for Boqun Feng
2020-08-07 7:42 ` [RFC v7 19/19] lockdep/selftest: Introduce recursion3 Boqun Feng
2020-08-27 7:54 ` [tip: locking/core] " tip-bot2 for Boqun Feng
2020-08-21 19:56 ` [RFC v7 00/19] lockdep: Support deadlock detection for recursive read locks Peter Zijlstra
2020-08-23 1:12 ` boqun.feng
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=20200807074238.1632519-2-boqun.feng@gmail.com \
--to=boqun.feng@gmail.com \
--cc=corbet@lwn.net \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=longman@redhat.com \
--cc=mingo@redhat.com \
--cc=peterz@infradead.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).