Re: [PATCH v4 6/9] rbtree: Implement generic latch_tree

2015-04-09 Thread Linus Torvalds
On Thu, Apr 9, 2015 at 10:12 AM, Linus Torvalds
 wrote:
>
> It's just unusual, which I think makes it slightly harder to read for
> a *human* just because it breaks the normal pattern of those things.
> But there's nothing technically wrong with it.

You could have written it as

  static __always_inline struct latch_tree_node *
  __lt_from_rb(struct rb_node *node, int idx)
  {
 return (void *)(node-idx);
  }

which is actually shorter, but even if that container_of() use looks a
bit unusual, I think the container_of() shows more clearly what you
actually want. Plus it would be more reliable if you ever end up
adding any other fields to the struct latch_tree_node.

So I wouldn't actually suggest using that "(node-idx)" format. I think
it should result in the exact same code, though.

 Linus
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v4 6/9] rbtree: Implement generic latch_tree

2015-04-09 Thread Linus Torvalds
On Thu, Apr 9, 2015 at 9:59 AM, Peter Zijlstra  wrote:
>
> I was a little surprised myself it worked, but its a constant after
> all so it 'should'.

Well, it should actually work for non-constants too, even when that
'idx' isn't inlined to one of the fixed constants. So even if this
will ever hit the "seq & 1" case for lookup, it should all work. It's
just an expression, after all.

All that is really required is that you can do '&(x->y)' on it, where
'x' is the type, and 'y' is the "member".

It's just unusual, which I think makes it slightly harder to read for
a *human* just because it breaks the normal pattern of those things.
But there's nothing technically wrong with it.

Linus
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v4 6/9] rbtree: Implement generic latch_tree

2015-04-09 Thread Peter Zijlstra
On Thu, Apr 09, 2015 at 09:31:16AM -0700, Linus Torvalds wrote:
> On Thu, Apr 9, 2015 at 5:13 AM, Peter Zijlstra  wrote:
> >
> >  struct latch_tree_node {
> > +   struct rb_node node[2];
> >  };
> >
> > +static __always_inline struct latch_tree_node *
> > +__lt_from_rb(struct rb_node *node, int idx)
> > +{
> > +   return container_of(node, struct latch_tree_node, node[idx]);
> > +}
> 
> Ugh. That syntax of offset_of() worries me a bit, but some grepping
> shows that we already use this form of offset_of() in parts of the
> kernel, so I guess it's fine.

I was a little surprised myself it worked, but its a constant after
all so it 'should'.

> Even with that small "Ugh", I do have to admit to preferring this to
> having the back-pointer.

Yeah me too, I'll respin the patches proper after I've given it some
actual runtime too.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v4 6/9] rbtree: Implement generic latch_tree

2015-04-09 Thread Linus Torvalds
On Thu, Apr 9, 2015 at 5:13 AM, Peter Zijlstra  wrote:
>
>  struct latch_tree_node {
> +   struct rb_node node[2];
>  };
>
> +static __always_inline struct latch_tree_node *
> +__lt_from_rb(struct rb_node *node, int idx)
> +{
> +   return container_of(node, struct latch_tree_node, node[idx]);
> +}

Ugh. That syntax of offset_of() worries me a bit, but some grepping
shows that we already use this form of offset_of() in parts of the
kernel, so I guess it's fine.

Even with that small "Ugh", I do have to admit to preferring this to
having the back-pointer.

Linus
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v4 6/9] rbtree: Implement generic latch_tree

2015-04-09 Thread Peter Zijlstra
On Thu, Apr 09, 2015 at 02:13:36PM +0200, Peter Zijlstra wrote:
> +struct module;
> +
> +struct mod_tree_node {
> + struct latch_tree_node node;
> + struct module *mod;
> +};

The module pointer should be first in this structure.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v4 6/9] rbtree: Implement generic latch_tree

2015-04-09 Thread Peter Zijlstra
On Thu, Apr 09, 2015 at 04:55:05PM +0800, Lai Jiangshan wrote:
> This sentence is talking about module.c not latch_tree.h. So I guess
> it is user(module.c)'s problem, not latch_tree.h's problem.
> 
> The user(module.c) can wrap the struct latch_tree_nodes and add @priv.

OK, took me a while to figure out exactly what and how. You mean
something like this, right?

(compile tested only)

---
 include/linux/module.h   |   11 -
 include/linux/rbtree_latch.h |   93 ++-
 kernel/module.c  |   33 +--
 3 files changed, 70 insertions(+), 67 deletions(-)

--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -211,6 +211,13 @@ enum module_state {
MODULE_STATE_UNFORMED,  /* Still setting it up. */
 };
 
+struct module;
+
+struct mod_tree_node {
+   struct latch_tree_node node;
+   struct module *mod;
+};
+
 struct module {
enum module_state state;
 
@@ -294,8 +301,8 @@ struct module {
 * core.node[0] to be in the same cacheline as the above entries,
 * we also assume ltn_init has a higher address than ltn_core.
 */
-   struct latch_tree_nodes ltn_core;
-   struct latch_tree_nodes ltn_init;
+   struct mod_tree_nodemtn_core;
+   struct mod_tree_nodemtn_init;
 
/* Size of RO sections of the module (text+rodata) */
unsigned int init_ro_size, core_ro_size;
--- a/include/linux/rbtree_latch.h
+++ b/include/linux/rbtree_latch.h
@@ -36,17 +36,7 @@
 #include 
 
 struct latch_tree_node {
-   /*
-* Because we have an array of two entries in struct latch_tree_nodes
-* it's not possible to use container_of() to get back to the
-* encapsulating structure; therefore we have to put in a back pointer.
-*/
-   void*priv;
-   struct rb_node  node;
-};
-
-struct latch_tree_nodes {
-   struct latch_tree_node node[2];
+   struct rb_node node[2];
 };
 
 struct latch_tree_root {
@@ -74,17 +64,25 @@ struct latch_tree_ops {
int  (*comp)(void *key, struct latch_tree_node *b);
 };
 
+static __always_inline struct latch_tree_node *
+__lt_from_rb(struct rb_node *node, int idx)
+{
+   return container_of(node, struct latch_tree_node, node[idx]);
+}
+
 static __always_inline void
-__lt_insert(struct latch_tree_node *ltn, struct rb_root *root,
+__lt_insert(struct latch_tree_node *ltn, struct latch_tree_root *ltr, int idx,
bool (*less)(struct latch_tree_node *a, struct latch_tree_node *b))
 {
+   struct rb_root *root = tree[idx];
struct rb_node **link = &root->rb_node;
+   struct rb_node *node = node[idx];
struct rb_node *parent = NULL;
struct latch_tree_node *ltp;
 
while (*link) {
parent = *link;
-   ltp = container_of(parent, struct latch_tree_node, node);
+   ltp = __lt_from_rb(parent, idx);
 
if (less(ltn, ltp))
link = &parent->rb_left;
@@ -92,32 +90,32 @@ __lt_insert(struct latch_tree_node *ltn,
link = &parent->rb_right;
}
 
-   rb_link_node_rcu(node, parent, link);
-   rb_insert_color(node, root);
+   rb_link_node_rcu(node, parent, link);
+   rb_insert_color(node, root);
 }
 
 static __always_inline void
-__lt_erase(struct latch_tree_node *ltn, struct rb_root *root)
+__lt_erase(struct latch_tree_node *ltn, struct latch_tree_root *ltr, int idx)
 {
-   rb_erase(node, root);
+   rb_erase(node[idx], tree[idx]);
 }
 
 static __always_inline struct latch_tree_node *
-__lt_find(void *key, struct rb_root *root,
- int (*comp)(void *key, struct latch_tree_node *ltn))
+__lt_find(void *key, struct latch_tree_root *ltr, int idx,
+ int (*comp)(void *key, struct latch_tree_node *node))
 {
-   struct rb_node *n = rcu_dereference_raw(root->rb_node);
+   struct rb_node *node = rcu_dereference_raw(ltr->tree[idx].rb_node);
struct latch_tree_node *ltn;
int c;
 
-   while (n) {
-   ltn = container_of(n, struct latch_tree_node, node);
+   while (node) {
+   ltn = __lt_from_rb(node, idx);
c = comp(key, ltn);
 
if (c < 0)
-   n = rcu_dereference_raw(n->rb_left);
+   node = rcu_dereference_raw(node->rb_left);
else if (c > 0)
-   n = rcu_dereference_raw(n->rb_right);
+   node = rcu_dereference_raw(node->rb_right);
else
return ltn;
}
@@ -126,65 +124,56 @@ __lt_find(void *key, struct rb_root *roo
 }
 
 /**
- * latch_tree_insert() - insert @nodes into the trees @root
- * @nodes: nodes to insert
- * @root: trees to insert @nodes into
- * @priv: pointer to node private data
+ * latch_tree_insert() - insert @node into the trees @root
+ * @node: nodes to insert
+ * @roo

Re: [PATCH v4 6/9] rbtree: Implement generic latch_tree

2015-04-09 Thread Lai Jiangshan
On 04/09/2015 04:14 PM, Peter Zijlstra wrote:
> On Thu, Apr 09, 2015 at 04:09:07PM +0800, Lai Jiangshan wrote:
>> On 04/09/2015 12:48 AM, Peter Zijlstra wrote:
>>
>>> +
>>> +struct latch_tree_node {
>>> +   /*
>>> +* Because we have an array of two entries in struct latch_tree_nodes
>>> +* it's not possible to use container_of() to get back to the
>>> +* encapsulating structure; therefore we have to put in a back pointer.
>>> +*/
>>> +   void*priv;
>>> +   struct rb_node  node;
>>> +};
>>
>> I don't think @priv is strictly needed. It is possible to use container_of()
>> to go back. @priv is even not used in this file (except the initialization).
>>
>> First, we can use container_of() to find encapsulating structure from the
>> struct latch_tree_nodeS.
>>
>> Second, we can add a @idx to __lt_insert() and __lt_find(), 
> 
> insert yes, find no. Remember that both nodes are in the _same_ tree.
> 
> There is no way of knowing if a tree node is an init or core node while
> iterating.
> .
> 

This sentence is talking about module.c not latch_tree.h. So I guess
it is user(module.c)'s problem, not latch_tree.h's problem.

The user(module.c) can wrap the struct latch_tree_nodes and add @priv.


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v4 6/9] rbtree: Implement generic latch_tree

2015-04-09 Thread Peter Zijlstra
On Thu, Apr 09, 2015 at 04:09:07PM +0800, Lai Jiangshan wrote:
> On 04/09/2015 12:48 AM, Peter Zijlstra wrote:
> 
> > +
> > +struct latch_tree_node {
> > +   /*
> > +* Because we have an array of two entries in struct latch_tree_nodes
> > +* it's not possible to use container_of() to get back to the
> > +* encapsulating structure; therefore we have to put in a back pointer.
> > +*/
> > +   void*priv;
> > +   struct rb_node  node;
> > +};
> 
> I don't think @priv is strictly needed. It is possible to use container_of()
> to go back. @priv is even not used in this file (except the initialization).
> 
> First, we can use container_of() to find encapsulating structure from the
> struct latch_tree_nodeS.
> 
> Second, we can add a @idx to __lt_insert() and __lt_find(), 

insert yes, find no. Remember that both nodes are in the _same_ tree.

There is no way of knowing if a tree node is an init or core node while
iterating.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v4 6/9] rbtree: Implement generic latch_tree

2015-04-09 Thread Lai Jiangshan
On 04/09/2015 12:48 AM, Peter Zijlstra wrote:

> +
> +struct latch_tree_node {
> + /*
> +  * Because we have an array of two entries in struct latch_tree_nodes
> +  * it's not possible to use container_of() to get back to the
> +  * encapsulating structure; therefore we have to put in a back pointer.
> +  */
> + void*priv;
> + struct rb_node  node;
> +};

I don't think @priv is strictly needed. It is possible to use container_of()
to go back. @priv is even not used in this file (except the initialization).

First, we can use container_of() to find encapsulating structure from the
struct latch_tree_nodeS.

Second, we can add a @idx to __lt_insert() and __lt_find(), thus we can
find the encapsulating latch_tree_nodes from rb_node or latch_tree_node.
and struct latch_tree_ops uses latch_tree_nodes instead.

Did I miss anything? If the @priv is possible to be removed, removing it will
simplify this file but it may add a little more code in the module.c where
the ltn_coreless() and ->comp() after.

If you do remove @priv, please also use rb_node instead of old latch_tree_node
and rename old latch_tree_nodes to latch_tree_node.

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/