All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
To: Peter Zijlstra <peterz@infradead.org>
Cc: mingo@kernel.org, rusty@rustcorp.com.au,
	mathieu.desnoyers@efficios.com, oleg@redhat.com,
	linux-kernel@vger.kernel.org, andi@firstfloor.org,
	rostedt@goodmis.org, tglx@linutronix.de,
	Michel Lespinasse <walken@google.com>,
	Andrea Arcangeli <aarcange@redhat.com>,
	David Woodhouse <David.Woodhouse@intel.com>,
	Rik van Riel <riel@redhat.com>
Subject: Re: [RFC][PATCH 7/9] rbtree: Implement generic latch_tree
Date: Mon, 2 Mar 2015 11:53:32 -0800	[thread overview]
Message-ID: <20150302195331.GW15405@linux.vnet.ibm.com> (raw)
In-Reply-To: <20150228213110.248177252@infradead.org>

On Sat, Feb 28, 2015 at 10:24:54PM +0100, Peter Zijlstra wrote:
> Implement a latched RB-tree in order to get RCU style lookups.
> 
> Cc: Michel Lespinasse <walken@google.com>
> Cc: Andrea Arcangeli <aarcange@redhat.com>
> Cc: David Woodhouse <David.Woodhouse@intel.com>
> Cc: Rik van Riel <riel@redhat.com>
> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
> Cc: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
> Cc: Oleg Nesterov <oleg@redhat.com>
> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>

The caller of latch_tree_erase() is required to wait for a grace period
before freeing the erased nodes?  Or am I missing something subtle here?

							Thanx, Paul

> ---
>  include/linux/rbtree_latch.h |  140 +++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 140 insertions(+)
> 
> --- /dev/null
> +++ b/include/linux/rbtree_latch.h
> @@ -0,0 +1,140 @@
> +/*
> + * Latched RB-trees
> + *
> + * Copyright (C) 2015 Intel Corp., Peter Zijlstra <peterz@infradead.org>
> + */
> +
> +#ifndef RB_TREE_LATCH_H
> +#define RB_TREE_LATCH_H
> +
> +#include <linux/rbtree.h>
> +#include <linux/seqlock.h>
> +
> +/*
> + * Since RB-trees have non atomic modifications they're not suited for
> + * RCU/lockless queries.
> + *
> + * Employ the latch technique -- see @raw_write_seqcount_latch -- to implement
> + * a latched RB-tree which does allow this by virtue of always having (at
> + * least) one stable copy of the tree.
> + *
> + * However, while we have the guarantee that there is at all times one stable
> + * copy, this does not guarantee an iteration will not observe modifications.
> + * What might have been a stable copy at the start of the iteration, need not
> + * remain so for the duration of the iteration.
> + *
> + * Therefore, this does require a lockless RB-tree iteration to be non-fatal in
> + * all circumstances; see the comment in lib/rbtree.c.
> + */
> +
> +struct latch_tree_node {
> +	void		*priv;
> +	struct rb_node	node;
> +};
> +
> +struct latch_tree_nodes {
> +	struct latch_tree_node node[2];
> +};
> +
> +struct latch_tree_root {
> +	seqcount_t	seq;
> +	struct rb_root	tree[2];
> +};
> +
> +struct latch_tree_ops {
> +	bool (*less)(struct latch_tree_node *a, struct latch_tree_node *b);
> +	int  (*comp)(void *key,                 struct latch_tree_node *b);
> +};
> +
> +static __always_inline void
> +__lt_insert(struct latch_tree_node *ltn, struct rb_root *root,
> +	    bool (*less)(struct latch_tree_node *a, struct latch_tree_node *b))
> +{
> +	struct rb_node **link = &root->rb_node;
> +	struct rb_node *parent = NULL;
> +	struct latch_tree_node *ltp;
> +
> +	while (*link) {
> +		parent = *link;
> +		ltp = container_of(parent, struct latch_tree_node, node);
> +
> +		if (less(ltn, ltp))
> +			link = &parent->rb_left;
> +		else
> +			link = &parent->rb_right;
> +	}
> +
> +	rb_link_node_rcu(&ltn->node, parent, link);
> +	rb_insert_color(&ltn->node, root);
> +}
> +
> +static __always_inline void
> +__lt_erase(struct latch_tree_node *ltn, struct rb_root *root)
> +{
> +	rb_erase(&ltn->node, root);
> +}
> +
> +static __always_inline struct latch_tree_node *
> +__lt_find(void *key, struct rb_root *root,
> +	  int (*comp)(void *key, struct latch_tree_node *ltn))
> +{
> +	struct rb_node *n = rcu_dereference_raw(root->rb_node);
> +	struct latch_tree_node *ltn;
> +	int c;
> +
> +	while (n) {
> +		ltn = container_of(n, struct latch_tree_node, node);
> +		c = comp(key, ltn);
> +
> +		if (c < 0)
> +			n = rcu_dereference_raw(n->rb_left);
> +		else if (c > 0)
> +			n = rcu_dereference_raw(n->rb_right);
> +		else
> +			return ltn;
> +	}
> +
> +	return NULL;
> +}
> +
> +static __always_inline void
> +latch_tree_insert(struct latch_tree_nodes *nodes,
> +		  struct latch_tree_root *root,
> +		  void *priv,
> +		  const struct latch_tree_ops *ops)
> +{
> +	nodes->node[0].priv = nodes->node[1].priv = priv;
> +
> +	raw_write_seqcount_latch(&root->seq);
> +	__lt_insert(&nodes->node[0], &root->tree[0], ops->less);
> +	raw_write_seqcount_latch(&root->seq);
> +	__lt_insert(&nodes->node[1], &root->tree[1], ops->less);
> +}
> +
> +static __always_inline void
> +latch_tree_erase(struct latch_tree_nodes *nodes,
> +		 struct latch_tree_root *root,
> +		 const struct latch_tree_ops *ops)
> +{
> +	raw_write_seqcount_latch(&root->seq);
> +	__lt_erase(&nodes->node[0], &root->tree[0]);
> +	raw_write_seqcount_latch(&root->seq);
> +	__lt_erase(&nodes->node[1], &root->tree[1]);
> +}
> +
> +static __always_inline struct latch_tree_node *
> +latch_tree_find(void *key, struct latch_tree_root *root,
> +		const struct latch_tree_ops *ops)
> +{
> +	struct latch_tree_node *node;
> +	unsigned int seq;
> +
> +	do {
> +		seq = raw_read_seqcount(&root->seq);
> +		node = __lt_find(key, &root->tree[seq & 1], ops->comp);
> +	} while (read_seqcount_retry(&root->seq, seq));
> +
> +	return node;
> +}
> +
> +#endif /* RB_TREE_LATCH_H */
> 
> 


  parent reply	other threads:[~2015-03-02 19:53 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-02-28 21:24 [RFC][PATCH 0/9] latched RB-trees and __module_address() Peter Zijlstra
2015-02-28 21:24 ` [RFC][PATCH 1/9] klp: Fix obvious RCU fail Peter Zijlstra
2015-03-01 20:09   ` Jiri Kosina
2015-03-02  8:35     ` Peter Zijlstra
2015-03-02  9:13       ` Jiri Kosina
2015-03-02 10:00         ` Peter Zijlstra
2015-03-02  9:21       ` Petr Mladek
2015-03-02  1:31   ` Masami Hiramatsu
2015-03-02 19:21   ` Paul E. McKenney
2015-03-02 21:07   ` Josh Poimboeuf
2015-02-28 21:24 ` [RFC][PATCH 2/9] module: Sanitize RCU usage and locking Peter Zijlstra
2015-03-02 11:16   ` Rusty Russell
2015-03-02 12:37     ` Peter Zijlstra
2015-03-02 19:37   ` Paul E. McKenney
2015-03-17 17:13     ` Peter Zijlstra
2015-02-28 21:24 ` [RFC][PATCH 3/9] module: Annotate module version magic Peter Zijlstra
2015-03-02 19:38   ` Paul E. McKenney
2015-02-28 21:24 ` [RFC][PATCH 4/9] module, jump_label: Fix module locking Peter Zijlstra
2015-03-02 19:39   ` Paul E. McKenney
2015-02-28 21:24 ` [RFC][PATCH 5/9] rbtree: Make lockless searches non-fatal Peter Zijlstra
2015-03-01 13:52   ` Mathieu Desnoyers
2015-03-02  8:27     ` Peter Zijlstra
2015-03-01 21:11   ` Michel Lespinasse
2015-03-02  7:46     ` Ingo Molnar
2015-03-02  8:23     ` Peter Zijlstra
2015-03-02  9:53       ` Peter Zijlstra
2015-02-28 21:24 ` [RFC][PATCH 6/9] seqlock: Better document raw_write_seqcount_latch() Peter Zijlstra
2015-03-01 14:02   ` Mathieu Desnoyers
2015-03-02  8:33     ` Peter Zijlstra
2015-03-02  8:51       ` Peter Zijlstra
2015-03-02 19:46         ` Paul E. McKenney
2015-03-01 21:12   ` Michel Lespinasse
2015-02-28 21:24 ` [RFC][PATCH 7/9] rbtree: Implement generic latch_tree Peter Zijlstra
2015-03-01 21:17   ` Michel Lespinasse
2015-03-02  8:05     ` Peter Zijlstra
2015-03-02 19:53   ` Paul E. McKenney [this message]
2015-03-17 17:24     ` Peter Zijlstra
2015-02-28 21:24 ` [RFC][PATCH 8/9] module: Optimize __module_address() using a latched RB-tree Peter Zijlstra
2015-02-28 21:24 ` [RFC][PATCH 9/9] module: Use __module_address() for module_address_lookup() Peter Zijlstra

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=20150302195331.GW15405@linux.vnet.ibm.com \
    --to=paulmck@linux.vnet.ibm.com \
    --cc=David.Woodhouse@intel.com \
    --cc=aarcange@redhat.com \
    --cc=andi@firstfloor.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mathieu.desnoyers@efficios.com \
    --cc=mingo@kernel.org \
    --cc=oleg@redhat.com \
    --cc=peterz@infradead.org \
    --cc=riel@redhat.com \
    --cc=rostedt@goodmis.org \
    --cc=rusty@rustcorp.com.au \
    --cc=tglx@linutronix.de \
    --cc=walken@google.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.