linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Boqun Feng <boqun.feng@gmail.com>
To: Peter Zijlstra <peterz@infradead.org>
Cc: linux-kernel@vger.kernel.org, Ingo Molnar <mingo@redhat.com>,
	Andrea Parri <parri.andrea@gmail.com>
Subject: Re: [RFC tip/locking/lockdep v5 05/17] lockdep: Extend __bfs() to work with multiple kinds of dependencies
Date: Thu, 22 Feb 2018 23:12:10 +0800	[thread overview]
Message-ID: <20180222151210.jwxjchywk4jfecyf@tardis> (raw)
In-Reply-To: <20180222142614.GR25201@hirez.programming.kicks-ass.net>

[-- Attachment #1: Type: text/plain, Size: 5419 bytes --]

On Thu, Feb 22, 2018 at 03:26:14PM +0100, Peter Zijlstra wrote:
> On Thu, Feb 22, 2018 at 03:08:52PM +0800, Boqun Feng wrote:
> > Now we have four kinds of dependencies in the dependency graph, and not
> > all the pathes carry strong dependencies, for example:
> > 
> > 	Given lock A, B, C, if we have:
> > 
> > 	CPU1			CPU2
> > 	=============		==============
> > 	write_lock(A);		read_lock(B);
> > 	read_lock(B);		write_lock(C);
> > 
> > 	then we have dependencies A--(NR)-->B, and B--(RN)-->C, (NR and
> > 	RN are to indicate the dependency kind), A actually doesn't have
> > 	strong dependency to C(IOW, C doesn't depend on A), to see this,
>                               ^ missing space
> 
> You're fairly consistent with not putting spaces before opening braces
> in text, please don't do this, this is not a C function call. Also

Got it.

> double check all your braces are matched, IIRC there's at least one that
> isn't closed in the previous patches.
> 

Sure, will do.

> > 	let's say we have a third CPU3 doing:
> > 
> > 	CPU3:
> > 	=============
> > 	write_lock(C);
> > 	write_lock(A);
> > 
> > 	, this is not a deadlock. However if we change the read_lock()
> > 	on CPU2 to a write_lock(), it's a deadlock then.
> > 
> > 	So A --(NR)--> B --(RN)--> C is not a strong dependency path but
> > 	A --(NR)--> B --(NN)-->C is a strong dependency path.
> 
> I'm not really satisfied with the above reasoning. I don't disagree, but
> if possible it would be nice to have something a little more solid.
> 

What do you mean by "solid"? You mean "A --(NR)--> B --(NN)-->C" is too
abstract, and want something like the below instead:

	CPU 1			CPU 2			CPU 3
	===========		============		============
	write_lock(A);
				write_lock(B);
	read_lock(B); // blocked			write_lock(C);
				write_lock(C); // blocked
							write_lock(A); // blocked

?


> 
> > We can generalize this as: If a path of dependencies doesn't have two
> > adjacent dependencies as (*R)--L-->(R*), where L is some lock, it is a
> > strong dependency path, otherwise it's not.
> > 
> > Now our mission is to make __bfs() traverse only the strong dependency
> > paths, which is simple: we record whether we have -(*R)-> at the current
> > tail of the path in lock_list::is_rr, and whenever we pick a dependency
> > in the traverse, we 1) make sure we don't pick a -(R*)-> dependency if
> > our current tail is -(*R)-> and 2) greedily pick a -(*N)-> as hard as
> > possible.
> > 
> > With this extension for __bfs(), we now need to initialize the root of
> > __bfs() properly(with a correct ->is_rr), to do so, we introduce some
>                   ^ another missing space
> 
> Also, I don't like is_rr as a name, have_xr might be better.
> 

Maybe "pick_xr", which means we pick a *R in the BFS search path for the
previous entry, then we can not pick R* for the next entry.

> Only if we combine *R with R* do we have RR.
> 
> > +/*
> > + * return -1 if no proper dependency could be picked
> > + * return 0 if a -(*N)-> dependency could be picked
> > + * return 1 if only a -(*R)-> dependency could be picked
> > + *
> > + * N: non-recursive lock
> > + * R: recursive read lock
> > + */
> > +static inline int pick_dep(u16 is_rr, u16 cap_dep)
> > +{
> > +	if (is_rr) { /* could only pick -(N*)-> */
> > +		if (cap_dep & DEP_NN_MASK)
> > +			return 0;
> > +		else if (cap_dep & DEP_NR_MASK)
> > +			return 1;
> > +		else
> > +			return -1;
> > +	} else {
> > +		if (cap_dep & DEP_NN_MASK || cap_dep & DEP_RN_MASK)
> 
> 	if (cap_dep & (DEP_NN_MASK | DEP_RN_MASK))

Good point!


> 
> > +			return 0;
> > +		else
> > +			return 1;
> > +	}
> > +}
> 
> However, I would suggest:
> 
> static inline bool is_xr(u16 dep)
> {
> 	return !!(dep & (DEP_NR_MASK | DEP_RR_MASK));
> }
> 
> static inline bool is_rx(u16 dep)
> {
> 	return !!(dep & (DEP_RN_MASK | DEP_RR_MASK));
> }
> 
> 
> > @@ -1095,11 +1179,18 @@ static enum bfs_result __bfs(struct lock_list *source_entry,
> >  		else
> >  			head = &lock->class->locks_before;
> >  
> > +		is_rr = lock->is_rr;
> > +
> >  		DEBUG_LOCKS_WARN_ON(!irqs_disabled());
> >  
> >  		list_for_each_entry_rcu(entry, head, entry) {
> >  			unsigned int cq_depth;
> >  
> > +			next_is_rr = pick_dep(is_rr, entry->dep);
> > +			if (next_is_rr < 0)
> > +				continue;
> > +			entry->is_rr = next_is_rr;
> 
> 		/* Skip *R -> R* relations */
> 		if (have_xr && is_rx(entry->dep))
> 			continue;

I don't think this works, if we pick a *R for previous entry, and for
current entry, we have RR, NN and NR, your approach will skip the
current entry, but actually we can pick NN or NR (of course, in __bfs(),
we can greedily pick NN, because if NR causes a deadlock, so does NN).

Note that lock_list::dep can be treated as a set/bitmap for different
kinds of dependencies between the same pair of locks.

Some related explanation of pick_dep() is put in the comment of
__bfs(), which is my bad ;-( I will reorder the code to have an
overall explanation for the algorithm, and put all related functions
after that.

Regards,
Boqun

> 
> 		entry->have_xr = is_xr(entry->dep);
> 
> Which to me is a much simpler construct, hmm?
> 
> > +
> >  			visit_lock_entry(entry, lock);
> >  			if (match(entry, data)) {
> >  				*target_entry = entry;
> 
> 
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

  reply	other threads:[~2018-02-22 15:08 UTC|newest]

Thread overview: 53+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-02-22  7:08 [RFC tip/locking/lockdep v5 00/17] lockdep: Support deadlock detection for recursive read locks Boqun Feng
2018-02-22  7:08 ` [RFC tip/locking/lockdep v5 01/17] lockdep: Demagic the return value of BFS Boqun Feng
2018-02-22  7:08 ` [RFC tip/locking/lockdep v5 02/17] lockdep: Make __bfs() visit every dependency until a match Boqun Feng
2018-02-22  7:08 ` [RFC tip/locking/lockdep v5 03/17] lockdep: Redefine LOCK_*_STATE* bits Boqun Feng
2018-02-22  7:08 ` [RFC tip/locking/lockdep v5 04/17] lockdep: Introduce lock_list::dep Boqun Feng
2018-02-23 11:55   ` Peter Zijlstra
2018-02-23 12:37     ` Boqun Feng
2018-02-24  5:32       ` Boqun Feng
2018-02-24  6:30         ` Boqun Feng
2018-02-24  8:38           ` Peter Zijlstra
2018-02-24  9:00             ` Boqun Feng
2018-02-24  9:26               ` Boqun Feng
2018-02-26  9:00                 ` Peter Zijlstra
2018-02-26 10:15                   ` Boqun Feng
2018-02-26 10:20                     ` Boqun Feng
2018-02-24  7:31         ` Boqun Feng
2018-02-22  7:08 ` [RFC tip/locking/lockdep v5 05/17] lockdep: Extend __bfs() to work with multiple kinds of dependencies Boqun Feng
2018-02-22 14:26   ` Peter Zijlstra
2018-02-22 15:12     ` Boqun Feng [this message]
2018-02-22 15:30       ` Peter Zijlstra
2018-02-22 15:51         ` Peter Zijlstra
2018-02-22 16:31           ` Boqun Feng
2018-02-23  5:02             ` Boqun Feng
2018-02-23 11:15               ` Peter Zijlstra
2018-02-22 16:08       ` Peter Zijlstra
2018-02-22 16:34         ` Boqun Feng
2018-02-22 16:32           ` Peter Zijlstra
2018-02-22  7:08 ` [RFC tip/locking/lockdep v5 06/17] lockdep: Support deadlock detection for recursive read in check_noncircular() Boqun Feng
2018-02-22 14:54   ` Peter Zijlstra
2018-02-22 15:16     ` Peter Zijlstra
2018-02-22 15:44       ` Boqun Feng
2018-02-22  7:08 ` [RFC tip/locking/lockdep v5 07/17] lockdep: Adjust check_redundant() for recursive read change Boqun Feng
2018-02-22 17:29   ` Peter Zijlstra
2018-03-16  8:20     ` Boqun Feng
2018-02-22  7:08 ` [RFC tip/locking/lockdep v5 08/17] lockdep: Fix recursive read lock related safe->unsafe detection Boqun Feng
2018-02-22 17:41   ` Peter Zijlstra
2018-02-22 17:46   ` Peter Zijlstra
2018-02-23  8:21     ` Boqun Feng
2018-02-23  8:58       ` Boqun Feng
2018-02-23 11:36         ` Peter Zijlstra
2018-02-22  7:08 ` [RFC tip/locking/lockdep v5 09/17] lockdep: Add recursive read locks into dependency graph Boqun Feng
2018-02-22  7:08 ` [RFC tip/locking/lockdep v5 10/17] lockdep/selftest: Add a R-L/L-W test case specific to chain cache behavior Boqun Feng
2018-02-22  7:08 ` [RFC tip/locking/lockdep v5 11/17] lockdep: Take read/write status in consideration when generate chainkey Boqun Feng
2018-02-22  7:08 ` [RFC tip/locking/lockdep v5 12/17] lockdep/selftest: Unleash irq_read_recursion2 and add more Boqun Feng
2018-02-22  7:09 ` [RFC tip/locking/lockdep v5 13/17] lockdep/selftest: Add more recursive read related test cases Boqun Feng
2018-02-22  7:09 ` [RFC tip/locking/lockdep v5 14/17] Revert "locking/lockdep/selftests: Fix mixed read-write ABBA tests" Boqun Feng
2018-02-22  7:09 ` [RFC tip/locking/lockdep v5 15/17] lockdep: Reduce the size of lock_list Boqun Feng
2018-02-23 11:38   ` Peter Zijlstra
2018-02-23 12:40     ` Boqun Feng
2018-02-22  7:09 ` [RFC tip/locking/lockdep v5 16/17] lockdep: Documention for recursive read lock detection reasoning Boqun Feng
2018-02-24 22:53   ` Andrea Parri
2018-02-27  2:32     ` Boqun Feng
2018-02-22  7:09 ` [RFC tip/locking/lockdep v5 17/17] MAINTAINERS: Add myself as a LOCKING PRIMITIVES reviewer 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=20180222151210.jwxjchywk4jfecyf@tardis \
    --to=boqun.feng@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=parri.andrea@gmail.com \
    --cc=peterz@infradead.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).