Skip to content

Commit 50a3803

Browse files
author
Peter Zijlstra
committed
rbtree: provide rb_find_rcu() / rb_find_add_rcu()
Much like latch_tree, add two RCU methods for the regular RB-tree, which can be used in conjunction with a seqcount to provide lockless lookups. Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Signed-off-by: "Peter Zijlstra (Intel)" <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Reviewed-by: Oleg Nesterov <[email protected]> Reviewed-by: "Masami Hiramatsu (Google)" <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 04b0162 commit 50a3803

File tree

1 file changed

+67
-0
lines changed

1 file changed

+67
-0
lines changed

include/linux/rbtree.h

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,42 @@ rb_find_add(struct rb_node *node, struct rb_root *tree,
244244
return NULL;
245245
}
246246

247+
/**
248+
* rb_find_add_rcu() - find equivalent @node in @tree, or add @node
249+
* @node: node to look-for / insert
250+
* @tree: tree to search / modify
251+
* @cmp: operator defining the node order
252+
*
253+
* Adds a Store-Release for link_node.
254+
*
255+
* Returns the rb_node matching @node, or NULL when no match is found and @node
256+
* is inserted.
257+
*/
258+
static __always_inline struct rb_node *
259+
rb_find_add_rcu(struct rb_node *node, struct rb_root *tree,
260+
int (*cmp)(struct rb_node *, const struct rb_node *))
261+
{
262+
struct rb_node **link = &tree->rb_node;
263+
struct rb_node *parent = NULL;
264+
int c;
265+
266+
while (*link) {
267+
parent = *link;
268+
c = cmp(node, parent);
269+
270+
if (c < 0)
271+
link = &parent->rb_left;
272+
else if (c > 0)
273+
link = &parent->rb_right;
274+
else
275+
return parent;
276+
}
277+
278+
rb_link_node_rcu(node, parent, link);
279+
rb_insert_color(node, tree);
280+
return NULL;
281+
}
282+
247283
/**
248284
* rb_find() - find @key in tree @tree
249285
* @key: key to match
@@ -272,6 +308,37 @@ rb_find(const void *key, const struct rb_root *tree,
272308
return NULL;
273309
}
274310

311+
/**
312+
* rb_find_rcu() - find @key in tree @tree
313+
* @key: key to match
314+
* @tree: tree to search
315+
* @cmp: operator defining the node order
316+
*
317+
* Notably, tree descent vs concurrent tree rotations is unsound and can result
318+
* in false-negatives.
319+
*
320+
* Returns the rb_node matching @key or NULL.
321+
*/
322+
static __always_inline struct rb_node *
323+
rb_find_rcu(const void *key, const struct rb_root *tree,
324+
int (*cmp)(const void *key, const struct rb_node *))
325+
{
326+
struct rb_node *node = tree->rb_node;
327+
328+
while (node) {
329+
int c = cmp(key, node);
330+
331+
if (c < 0)
332+
node = rcu_dereference_raw(node->rb_left);
333+
else if (c > 0)
334+
node = rcu_dereference_raw(node->rb_right);
335+
else
336+
return node;
337+
}
338+
339+
return NULL;
340+
}
341+
275342
/**
276343
* rb_find_first() - find the first @key in @tree
277344
* @key: key to match

0 commit comments

Comments
 (0)