LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
From: Yuyang Du <duyuyang@gmail.com>
To: peterz@infradead.org, will.deacon@arm.com, mingo@kernel.org
Cc: bvanassche@acm.org, ming.lei@redhat.com, frederic@kernel.org,
	tglx@linutronix.de, boqun.feng@gmail.com,
	linux-kernel@vger.kernel.org, Yuyang Du <duyuyang@gmail.com>
Subject: [PATCH 04/17] locking/lockdep: Update direct dependency's read-write type if it exists
Date: Mon, 13 May 2019 17:11:50 +0800	[thread overview]
Message-ID: <20190513091203.7299-5-duyuyang@gmail.com> (raw)
In-Reply-To: <20190513091203.7299-1-duyuyang@gmail.com>

When adding a dependency, if the dependency exists - be it direct or
indirect - the dependency's read-write type may be updated.

We can keep all different-typed dependencies, but for simplicity we just
"upgrade" lock types if possible, making them more exlusive (in the order:
recursive read -> read -> write.

For indirect dependency, we do the redundancy check only when it has no
read locks (i.e., write-lock ended dependency); this makes the redundancy
check less complicated, which matters only when CONFIG_LOCKDEP_SMALL.

Signed-off-by: Yuyang Du <duyuyang@gmail.com>
---
 kernel/locking/lockdep.c | 61 ++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 57 insertions(+), 4 deletions(-)

diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
index 0617375..27ca55f 100644
--- a/kernel/locking/lockdep.c
+++ b/kernel/locking/lockdep.c
@@ -1734,6 +1734,16 @@ static inline int get_lock_type2(struct lock_list *lock)
 	return lock->lock_type[1];
 }
 
+static inline void set_lock_type1(struct lock_list *lock, int read)
+{
+	lock->lock_type[0] = (u16)read;
+}
+
+static inline void set_lock_type2(struct lock_list *lock, int read)
+{
+	lock->lock_type[1] = (u16)read;
+}
+
 /*
  * Check that the dependency graph starting at <src> can lead to
  * <target> or not. Print an error and return 0 if it does.
@@ -1814,6 +1824,32 @@ static inline int get_lock_type2(struct lock_list *lock)
 	ret = check_path(hlock_class(target), &src_entry, &target_entry);
 
 	if (!ret) {
+		struct lock_list *parent;
+
+		/*
+		 * Do this indirect dependency has the same type as the
+		 * direct dependency?
+		 *
+		 * Actually, we keep the more exclusive lock type
+		 * between the indirect and direct dependencies by
+		 * "upgrading" the indirect dependency's lock type if
+		 * needed, and then consider this redundant.
+		 */
+
+		/* Target end lock type: */
+		if (target->read < get_lock_type2(target_entry))
+			set_lock_type2(target_entry, target->read)
+
+		/* Source end lock type: */
+		parent = find_next_dep_in_path(&src_entry, target_entry);
+		if (!parent) {
+			DEBUG_LOCKS_WARN_ON(1);
+			return 0;
+		}
+
+		if (src->read < get_lock_type1(parent))
+			set_lock_type1(parent, src->read)
+
 		debug_atomic_inc(nr_redundant);
 		ret = 2;
 	} else if (ret < 0)
@@ -2479,6 +2515,17 @@ static inline void inc_chains(void)
 	 */
 	list_for_each_entry(entry, &hlock_class(prev)->locks_after, entry) {
 		if (entry->class == hlock_class(next)) {
+			/*
+			 * For direct dependency, smaller type value
+			 * generally means more exlusive; we keep the
+			 * more exlusive ones, in other words, we
+			 * "upgrade" the dependency if we can.
+			 */
+			if (prev->read < get_lock_type1(entry))
+				set_lock_type1(entry, prev->read);
+			if (next->read < get_lock_type2(entry))
+				set_lock_type2(entry, next->read);
+
 			if (distance == 1)
 				entry->distance = 1;
 			return 1;
@@ -2487,11 +2534,17 @@ static inline void inc_chains(void)
 
 #ifdef CONFIG_LOCKDEP_SMALL
 	/*
-	 * Is the <prev> -> <next> link redundant?
+	 * Only when this dependency has no read lock/locks (i.e.,
+	 * write-write dependency), we do redundancy check.
 	 */
-	ret = check_redundant(prev, next);
-	if (ret != 1)
-		return ret;
+	if (!get_dep_type(prev, next)) {
+		/*
+		 * Is the <prev> -> <next> link redundant?
+		 */
+		ret = check_redundant(prev, next);
+		if (ret != 1)
+			return ret;
+	}
 #endif
 
 	if (!trace->nr_entries && !save_trace(trace))
-- 
1.8.3.1


  parent reply	other threads:[~2019-05-13  9:13 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-05-13  9:11 [PATCH 00/17] Support for read-write lock deadlock detection Yuyang Du
2019-05-13  9:11 ` [PATCH 01/17] locking/lockdep: Add lock type enum to explicitly specify read or write locks Yuyang Du
2019-05-13 11:45   ` Peter Zijlstra
2019-05-14  1:31     ` Yuyang Du
2019-05-14 12:04       ` Peter Zijlstra
2019-05-13  9:11 ` [PATCH 02/17] locking/lockdep: Add read-write type for dependency Yuyang Du
2019-05-13  9:11 ` [PATCH 03/17] locking/lockdep: Add helper functions to operate on the searched path Yuyang Du
2019-05-13  9:11 ` Yuyang Du [this message]
2019-05-13  9:11 ` [PATCH 05/17] locking/lockdep: Rename deadlock check functions Yuyang Du
2019-05-13  9:11 ` [PATCH 06/17] locking/lockdep: Adjust BFS algorithm to support multiple matches Yuyang Du
2019-05-13  9:11 ` [PATCH 07/17] locking/lockdep: Introduce mark_lock_unaccessed() Yuyang Du
2019-05-13  9:11 ` [PATCH 08/17] locking/lockdep: Introduce chain_hlocks_type for held lock's read-write type Yuyang Du
2019-05-13  9:11 ` [PATCH 09/17] locking/lockdep: Hash held lock's read-write type into chain key Yuyang Du
2019-05-13  9:11 ` [PATCH 10/17] locking/lockdep: Support read-write lock's deadlock detection Yuyang Du
2019-05-13  9:11 ` [PATCH 11/17] locking/lockdep: Adjust lockdep selftest cases Yuyang Du
2019-05-13  9:11 ` [PATCH 12/17] locking/lockdep: Remove useless lock type assignment Yuyang Du
2019-05-13  9:11 ` [PATCH 13/17] locking/lockdep: Add nest lock type Yuyang Du
2019-05-13  9:12 ` [PATCH 14/17] locking/lockdep: Support recursive read locks Yuyang Du
2019-05-13  9:12 ` [PATCH 15/17] locking/lockdep: Adjust selftest case for recursive read lock Yuyang Du
2019-05-13  9:12 ` [PATCH 16/17] locking/lockdep: Add more lockdep selftest cases Yuyang Du
2019-05-13  9:12 ` [PATCH 17/17] locking/lockdep: Remove irq-safe to irq-unsafe read check Yuyang Du
2019-05-13  9:17 ` [PATCH 00/17] Support for read-write lock deadlock detection Yuyang Du

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=20190513091203.7299-5-duyuyang@gmail.com \
    --to=duyuyang@gmail.com \
    --cc=boqun.feng@gmail.com \
    --cc=bvanassche@acm.org \
    --cc=frederic@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=ming.lei@redhat.com \
    --cc=mingo@kernel.org \
    --cc=peterz@infradead.org \
    --cc=tglx@linutronix.de \
    --cc=will.deacon@arm.com \
    --subject='Re: [PATCH 04/17] locking/lockdep: Update direct dependency'\''s read-write type if it exists' \
    /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

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).