11a59d1b8SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */
203da23a3SArnaldo Carvalho de Melo /*
303da23a3SArnaldo Carvalho de Melo Red Black Trees
403da23a3SArnaldo Carvalho de Melo (C) 1999 Andrea Arcangeli <[email protected]>
503da23a3SArnaldo Carvalho de Melo
603da23a3SArnaldo Carvalho de Melo
703da23a3SArnaldo Carvalho de Melo linux/include/linux/rbtree.h
803da23a3SArnaldo Carvalho de Melo
903da23a3SArnaldo Carvalho de Melo To use rbtrees you'll have to implement your own insert and search cores.
1003da23a3SArnaldo Carvalho de Melo This will avoid us to use callbacks and to drop drammatically performances.
1103da23a3SArnaldo Carvalho de Melo I know it's not the cleaner way, but in C (not in C++) to get
1203da23a3SArnaldo Carvalho de Melo performances and genericity...
1303da23a3SArnaldo Carvalho de Melo
1414bbe3e3SMatthew Wilcox (Oracle) See Documentation/core-api/rbtree.rst for documentation and samples.
1503da23a3SArnaldo Carvalho de Melo */
1603da23a3SArnaldo Carvalho de Melo
1703da23a3SArnaldo Carvalho de Melo #ifndef __TOOLS_LINUX_PERF_RBTREE_H
1803da23a3SArnaldo Carvalho de Melo #define __TOOLS_LINUX_PERF_RBTREE_H
1903da23a3SArnaldo Carvalho de Melo
2003da23a3SArnaldo Carvalho de Melo #include <linux/kernel.h>
2103da23a3SArnaldo Carvalho de Melo #include <linux/stddef.h>
2203da23a3SArnaldo Carvalho de Melo
2303da23a3SArnaldo Carvalho de Melo struct rb_node {
2403da23a3SArnaldo Carvalho de Melo unsigned long __rb_parent_color;
2503da23a3SArnaldo Carvalho de Melo struct rb_node *rb_right;
2603da23a3SArnaldo Carvalho de Melo struct rb_node *rb_left;
2703da23a3SArnaldo Carvalho de Melo } __attribute__((aligned(sizeof(long))));
2803da23a3SArnaldo Carvalho de Melo /* The alignment might seem pointless, but allegedly CRIS needs it */
2903da23a3SArnaldo Carvalho de Melo
3003da23a3SArnaldo Carvalho de Melo struct rb_root {
3103da23a3SArnaldo Carvalho de Melo struct rb_node *rb_node;
3203da23a3SArnaldo Carvalho de Melo };
3303da23a3SArnaldo Carvalho de Melo
3403da23a3SArnaldo Carvalho de Melo #define rb_parent(r) ((struct rb_node *)((r)->__rb_parent_color & ~3))
3503da23a3SArnaldo Carvalho de Melo
3603da23a3SArnaldo Carvalho de Melo #define RB_ROOT (struct rb_root) { NULL, }
3703da23a3SArnaldo Carvalho de Melo #define rb_entry(ptr, type, member) container_of(ptr, type, member)
3803da23a3SArnaldo Carvalho de Melo
393aef2cadSDavidlohr Bueso #define RB_EMPTY_ROOT(root) (READ_ONCE((root)->rb_node) == NULL)
4003da23a3SArnaldo Carvalho de Melo
4103da23a3SArnaldo Carvalho de Melo /* 'empty' nodes are nodes that are known not to be inserted in an rbtree */
4203da23a3SArnaldo Carvalho de Melo #define RB_EMPTY_NODE(node) \
4303da23a3SArnaldo Carvalho de Melo ((node)->__rb_parent_color == (unsigned long)(node))
4403da23a3SArnaldo Carvalho de Melo #define RB_CLEAR_NODE(node) \
4503da23a3SArnaldo Carvalho de Melo ((node)->__rb_parent_color = (unsigned long)(node))
4603da23a3SArnaldo Carvalho de Melo
4703da23a3SArnaldo Carvalho de Melo
4803da23a3SArnaldo Carvalho de Melo extern void rb_insert_color(struct rb_node *, struct rb_root *);
4903da23a3SArnaldo Carvalho de Melo extern void rb_erase(struct rb_node *, struct rb_root *);
5003da23a3SArnaldo Carvalho de Melo
5103da23a3SArnaldo Carvalho de Melo
5203da23a3SArnaldo Carvalho de Melo /* Find logical next and previous nodes in a tree */
5303da23a3SArnaldo Carvalho de Melo extern struct rb_node *rb_next(const struct rb_node *);
5403da23a3SArnaldo Carvalho de Melo extern struct rb_node *rb_prev(const struct rb_node *);
5503da23a3SArnaldo Carvalho de Melo extern struct rb_node *rb_first(const struct rb_root *);
5603da23a3SArnaldo Carvalho de Melo extern struct rb_node *rb_last(const struct rb_root *);
5703da23a3SArnaldo Carvalho de Melo
5803da23a3SArnaldo Carvalho de Melo /* Postorder iteration - always visit the parent after its children */
5903da23a3SArnaldo Carvalho de Melo extern struct rb_node *rb_first_postorder(const struct rb_root *);
6003da23a3SArnaldo Carvalho de Melo extern struct rb_node *rb_next_postorder(const struct rb_node *);
6103da23a3SArnaldo Carvalho de Melo
6203da23a3SArnaldo Carvalho de Melo /* Fast replacement of a single node without remove/rebalance/add/rebalance */
6303da23a3SArnaldo Carvalho de Melo extern void rb_replace_node(struct rb_node *victim, struct rb_node *new,
6403da23a3SArnaldo Carvalho de Melo struct rb_root *root);
6503da23a3SArnaldo Carvalho de Melo
rb_link_node(struct rb_node * node,struct rb_node * parent,struct rb_node ** rb_link)6603da23a3SArnaldo Carvalho de Melo static inline void rb_link_node(struct rb_node *node, struct rb_node *parent,
6703da23a3SArnaldo Carvalho de Melo struct rb_node **rb_link)
6803da23a3SArnaldo Carvalho de Melo {
6903da23a3SArnaldo Carvalho de Melo node->__rb_parent_color = (unsigned long)parent;
7003da23a3SArnaldo Carvalho de Melo node->rb_left = node->rb_right = NULL;
7103da23a3SArnaldo Carvalho de Melo
7203da23a3SArnaldo Carvalho de Melo *rb_link = node;
7303da23a3SArnaldo Carvalho de Melo }
7403da23a3SArnaldo Carvalho de Melo
7503da23a3SArnaldo Carvalho de Melo #define rb_entry_safe(ptr, type, member) \
7603da23a3SArnaldo Carvalho de Melo ({ typeof(ptr) ____ptr = (ptr); \
7703da23a3SArnaldo Carvalho de Melo ____ptr ? rb_entry(____ptr, type, member) : NULL; \
7803da23a3SArnaldo Carvalho de Melo })
7903da23a3SArnaldo Carvalho de Melo
803aef2cadSDavidlohr Bueso /**
813aef2cadSDavidlohr Bueso * rbtree_postorder_for_each_entry_safe - iterate in post-order over rb_root of
823aef2cadSDavidlohr Bueso * given type allowing the backing memory of @pos to be invalidated
833aef2cadSDavidlohr Bueso *
843aef2cadSDavidlohr Bueso * @pos: the 'type *' to use as a loop cursor.
853aef2cadSDavidlohr Bueso * @n: another 'type *' to use as temporary storage
863aef2cadSDavidlohr Bueso * @root: 'rb_root *' of the rbtree.
873aef2cadSDavidlohr Bueso * @field: the name of the rb_node field within 'type'.
883aef2cadSDavidlohr Bueso *
893aef2cadSDavidlohr Bueso * rbtree_postorder_for_each_entry_safe() provides a similar guarantee as
903aef2cadSDavidlohr Bueso * list_for_each_entry_safe() and allows the iteration to continue independent
913aef2cadSDavidlohr Bueso * of changes to @pos by the body of the loop.
923aef2cadSDavidlohr Bueso *
933aef2cadSDavidlohr Bueso * Note, however, that it cannot handle other modifications that re-order the
943aef2cadSDavidlohr Bueso * rbtree it is iterating over. This includes calling rb_erase() on @pos, as
953aef2cadSDavidlohr Bueso * rb_erase() may rebalance the tree, causing us to miss some nodes.
9603da23a3SArnaldo Carvalho de Melo */
973aef2cadSDavidlohr Bueso #define rbtree_postorder_for_each_entry_safe(pos, n, root, field) \
983aef2cadSDavidlohr Bueso for (pos = rb_entry_safe(rb_first_postorder(root), typeof(*pos), field); \
993aef2cadSDavidlohr Bueso pos && ({ n = rb_entry_safe(rb_next_postorder(&pos->field), \
1003aef2cadSDavidlohr Bueso typeof(*pos), field); 1; }); \
1013aef2cadSDavidlohr Bueso pos = n)
1023aef2cadSDavidlohr Bueso
rb_erase_init(struct rb_node * n,struct rb_root * root)10303da23a3SArnaldo Carvalho de Melo static inline void rb_erase_init(struct rb_node *n, struct rb_root *root)
10403da23a3SArnaldo Carvalho de Melo {
10503da23a3SArnaldo Carvalho de Melo rb_erase(n, root);
10603da23a3SArnaldo Carvalho de Melo RB_CLEAR_NODE(n);
10703da23a3SArnaldo Carvalho de Melo }
108c7d4f7eeSMichel Lespinasse
109c7d4f7eeSMichel Lespinasse /*
110c7d4f7eeSMichel Lespinasse * Leftmost-cached rbtrees.
111c7d4f7eeSMichel Lespinasse *
112c7d4f7eeSMichel Lespinasse * We do not cache the rightmost node based on footprint
113c7d4f7eeSMichel Lespinasse * size vs number of potential users that could benefit
114c7d4f7eeSMichel Lespinasse * from O(1) rb_last(). Just not worth it, users that want
115c7d4f7eeSMichel Lespinasse * this feature can always implement the logic explicitly.
116c7d4f7eeSMichel Lespinasse * Furthermore, users that want to cache both pointers may
117c7d4f7eeSMichel Lespinasse * find it a bit asymmetric, but that's ok.
118c7d4f7eeSMichel Lespinasse */
119c7d4f7eeSMichel Lespinasse struct rb_root_cached {
120c7d4f7eeSMichel Lespinasse struct rb_root rb_root;
121c7d4f7eeSMichel Lespinasse struct rb_node *rb_leftmost;
122c7d4f7eeSMichel Lespinasse };
123c7d4f7eeSMichel Lespinasse
124c7d4f7eeSMichel Lespinasse #define RB_ROOT_CACHED (struct rb_root_cached) { {NULL, }, NULL }
125c7d4f7eeSMichel Lespinasse
126c7d4f7eeSMichel Lespinasse /* Same as rb_first(), but O(1) */
127c7d4f7eeSMichel Lespinasse #define rb_first_cached(root) (root)->rb_leftmost
128c7d4f7eeSMichel Lespinasse
rb_insert_color_cached(struct rb_node * node,struct rb_root_cached * root,bool leftmost)129c7d4f7eeSMichel Lespinasse static inline void rb_insert_color_cached(struct rb_node *node,
130c7d4f7eeSMichel Lespinasse struct rb_root_cached *root,
131c7d4f7eeSMichel Lespinasse bool leftmost)
132c7d4f7eeSMichel Lespinasse {
133c7d4f7eeSMichel Lespinasse if (leftmost)
134c7d4f7eeSMichel Lespinasse root->rb_leftmost = node;
135c7d4f7eeSMichel Lespinasse rb_insert_color(node, &root->rb_root);
136c7d4f7eeSMichel Lespinasse }
137c7d4f7eeSMichel Lespinasse
rb_erase_cached(struct rb_node * node,struct rb_root_cached * root)138c7d4f7eeSMichel Lespinasse static inline void rb_erase_cached(struct rb_node *node,
139c7d4f7eeSMichel Lespinasse struct rb_root_cached *root)
140c7d4f7eeSMichel Lespinasse {
141c7d4f7eeSMichel Lespinasse if (root->rb_leftmost == node)
142c7d4f7eeSMichel Lespinasse root->rb_leftmost = rb_next(node);
143c7d4f7eeSMichel Lespinasse rb_erase(node, &root->rb_root);
144c7d4f7eeSMichel Lespinasse }
145c7d4f7eeSMichel Lespinasse
rb_replace_node_cached(struct rb_node * victim,struct rb_node * new,struct rb_root_cached * root)146c7d4f7eeSMichel Lespinasse static inline void rb_replace_node_cached(struct rb_node *victim,
147c7d4f7eeSMichel Lespinasse struct rb_node *new,
148c7d4f7eeSMichel Lespinasse struct rb_root_cached *root)
149c7d4f7eeSMichel Lespinasse {
150c7d4f7eeSMichel Lespinasse if (root->rb_leftmost == victim)
151c7d4f7eeSMichel Lespinasse root->rb_leftmost = new;
152c7d4f7eeSMichel Lespinasse rb_replace_node(victim, new, &root->rb_root);
153c7d4f7eeSMichel Lespinasse }
154c7d4f7eeSMichel Lespinasse
155*2d24dd57SPeter Zijlstra /*
156*2d24dd57SPeter Zijlstra * The below helper functions use 2 operators with 3 different
157*2d24dd57SPeter Zijlstra * calling conventions. The operators are related like:
158*2d24dd57SPeter Zijlstra *
159*2d24dd57SPeter Zijlstra * comp(a->key,b) < 0 := less(a,b)
160*2d24dd57SPeter Zijlstra * comp(a->key,b) > 0 := less(b,a)
161*2d24dd57SPeter Zijlstra * comp(a->key,b) == 0 := !less(a,b) && !less(b,a)
162*2d24dd57SPeter Zijlstra *
163*2d24dd57SPeter Zijlstra * If these operators define a partial order on the elements we make no
164*2d24dd57SPeter Zijlstra * guarantee on which of the elements matching the key is found. See
165*2d24dd57SPeter Zijlstra * rb_find().
166*2d24dd57SPeter Zijlstra *
167*2d24dd57SPeter Zijlstra * The reason for this is to allow the find() interface without requiring an
168*2d24dd57SPeter Zijlstra * on-stack dummy object, which might not be feasible due to object size.
169*2d24dd57SPeter Zijlstra */
170*2d24dd57SPeter Zijlstra
171*2d24dd57SPeter Zijlstra /**
172*2d24dd57SPeter Zijlstra * rb_add_cached() - insert @node into the leftmost cached tree @tree
173*2d24dd57SPeter Zijlstra * @node: node to insert
174*2d24dd57SPeter Zijlstra * @tree: leftmost cached tree to insert @node into
175*2d24dd57SPeter Zijlstra * @less: operator defining the (partial) node order
176*2d24dd57SPeter Zijlstra */
177*2d24dd57SPeter Zijlstra static __always_inline void
rb_add_cached(struct rb_node * node,struct rb_root_cached * tree,bool (* less)(struct rb_node *,const struct rb_node *))178*2d24dd57SPeter Zijlstra rb_add_cached(struct rb_node *node, struct rb_root_cached *tree,
179*2d24dd57SPeter Zijlstra bool (*less)(struct rb_node *, const struct rb_node *))
180*2d24dd57SPeter Zijlstra {
181*2d24dd57SPeter Zijlstra struct rb_node **link = &tree->rb_root.rb_node;
182*2d24dd57SPeter Zijlstra struct rb_node *parent = NULL;
183*2d24dd57SPeter Zijlstra bool leftmost = true;
184*2d24dd57SPeter Zijlstra
185*2d24dd57SPeter Zijlstra while (*link) {
186*2d24dd57SPeter Zijlstra parent = *link;
187*2d24dd57SPeter Zijlstra if (less(node, parent)) {
188*2d24dd57SPeter Zijlstra link = &parent->rb_left;
189*2d24dd57SPeter Zijlstra } else {
190*2d24dd57SPeter Zijlstra link = &parent->rb_right;
191*2d24dd57SPeter Zijlstra leftmost = false;
192*2d24dd57SPeter Zijlstra }
193*2d24dd57SPeter Zijlstra }
194*2d24dd57SPeter Zijlstra
195*2d24dd57SPeter Zijlstra rb_link_node(node, parent, link);
196*2d24dd57SPeter Zijlstra rb_insert_color_cached(node, tree, leftmost);
197*2d24dd57SPeter Zijlstra }
198*2d24dd57SPeter Zijlstra
199*2d24dd57SPeter Zijlstra /**
200*2d24dd57SPeter Zijlstra * rb_add() - insert @node into @tree
201*2d24dd57SPeter Zijlstra * @node: node to insert
202*2d24dd57SPeter Zijlstra * @tree: tree to insert @node into
203*2d24dd57SPeter Zijlstra * @less: operator defining the (partial) node order
204*2d24dd57SPeter Zijlstra */
205*2d24dd57SPeter Zijlstra static __always_inline void
rb_add(struct rb_node * node,struct rb_root * tree,bool (* less)(struct rb_node *,const struct rb_node *))206*2d24dd57SPeter Zijlstra rb_add(struct rb_node *node, struct rb_root *tree,
207*2d24dd57SPeter Zijlstra bool (*less)(struct rb_node *, const struct rb_node *))
208*2d24dd57SPeter Zijlstra {
209*2d24dd57SPeter Zijlstra struct rb_node **link = &tree->rb_node;
210*2d24dd57SPeter Zijlstra struct rb_node *parent = NULL;
211*2d24dd57SPeter Zijlstra
212*2d24dd57SPeter Zijlstra while (*link) {
213*2d24dd57SPeter Zijlstra parent = *link;
214*2d24dd57SPeter Zijlstra if (less(node, parent))
215*2d24dd57SPeter Zijlstra link = &parent->rb_left;
216*2d24dd57SPeter Zijlstra else
217*2d24dd57SPeter Zijlstra link = &parent->rb_right;
218*2d24dd57SPeter Zijlstra }
219*2d24dd57SPeter Zijlstra
220*2d24dd57SPeter Zijlstra rb_link_node(node, parent, link);
221*2d24dd57SPeter Zijlstra rb_insert_color(node, tree);
222*2d24dd57SPeter Zijlstra }
223*2d24dd57SPeter Zijlstra
224*2d24dd57SPeter Zijlstra /**
225*2d24dd57SPeter Zijlstra * rb_find_add() - find equivalent @node in @tree, or add @node
226*2d24dd57SPeter Zijlstra * @node: node to look-for / insert
227*2d24dd57SPeter Zijlstra * @tree: tree to search / modify
228*2d24dd57SPeter Zijlstra * @cmp: operator defining the node order
229*2d24dd57SPeter Zijlstra *
230*2d24dd57SPeter Zijlstra * Returns the rb_node matching @node, or NULL when no match is found and @node
231*2d24dd57SPeter Zijlstra * is inserted.
232*2d24dd57SPeter Zijlstra */
233*2d24dd57SPeter Zijlstra static __always_inline struct rb_node *
rb_find_add(struct rb_node * node,struct rb_root * tree,int (* cmp)(struct rb_node *,const struct rb_node *))234*2d24dd57SPeter Zijlstra rb_find_add(struct rb_node *node, struct rb_root *tree,
235*2d24dd57SPeter Zijlstra int (*cmp)(struct rb_node *, const struct rb_node *))
236*2d24dd57SPeter Zijlstra {
237*2d24dd57SPeter Zijlstra struct rb_node **link = &tree->rb_node;
238*2d24dd57SPeter Zijlstra struct rb_node *parent = NULL;
239*2d24dd57SPeter Zijlstra int c;
240*2d24dd57SPeter Zijlstra
241*2d24dd57SPeter Zijlstra while (*link) {
242*2d24dd57SPeter Zijlstra parent = *link;
243*2d24dd57SPeter Zijlstra c = cmp(node, parent);
244*2d24dd57SPeter Zijlstra
245*2d24dd57SPeter Zijlstra if (c < 0)
246*2d24dd57SPeter Zijlstra link = &parent->rb_left;
247*2d24dd57SPeter Zijlstra else if (c > 0)
248*2d24dd57SPeter Zijlstra link = &parent->rb_right;
249*2d24dd57SPeter Zijlstra else
250*2d24dd57SPeter Zijlstra return parent;
251*2d24dd57SPeter Zijlstra }
252*2d24dd57SPeter Zijlstra
253*2d24dd57SPeter Zijlstra rb_link_node(node, parent, link);
254*2d24dd57SPeter Zijlstra rb_insert_color(node, tree);
255*2d24dd57SPeter Zijlstra return NULL;
256*2d24dd57SPeter Zijlstra }
257*2d24dd57SPeter Zijlstra
258*2d24dd57SPeter Zijlstra /**
259*2d24dd57SPeter Zijlstra * rb_find() - find @key in tree @tree
260*2d24dd57SPeter Zijlstra * @key: key to match
261*2d24dd57SPeter Zijlstra * @tree: tree to search
262*2d24dd57SPeter Zijlstra * @cmp: operator defining the node order
263*2d24dd57SPeter Zijlstra *
264*2d24dd57SPeter Zijlstra * Returns the rb_node matching @key or NULL.
265*2d24dd57SPeter Zijlstra */
266*2d24dd57SPeter Zijlstra static __always_inline struct rb_node *
rb_find(const void * key,const struct rb_root * tree,int (* cmp)(const void * key,const struct rb_node *))267*2d24dd57SPeter Zijlstra rb_find(const void *key, const struct rb_root *tree,
268*2d24dd57SPeter Zijlstra int (*cmp)(const void *key, const struct rb_node *))
269*2d24dd57SPeter Zijlstra {
270*2d24dd57SPeter Zijlstra struct rb_node *node = tree->rb_node;
271*2d24dd57SPeter Zijlstra
272*2d24dd57SPeter Zijlstra while (node) {
273*2d24dd57SPeter Zijlstra int c = cmp(key, node);
274*2d24dd57SPeter Zijlstra
275*2d24dd57SPeter Zijlstra if (c < 0)
276*2d24dd57SPeter Zijlstra node = node->rb_left;
277*2d24dd57SPeter Zijlstra else if (c > 0)
278*2d24dd57SPeter Zijlstra node = node->rb_right;
279*2d24dd57SPeter Zijlstra else
280*2d24dd57SPeter Zijlstra return node;
281*2d24dd57SPeter Zijlstra }
282*2d24dd57SPeter Zijlstra
283*2d24dd57SPeter Zijlstra return NULL;
284*2d24dd57SPeter Zijlstra }
285*2d24dd57SPeter Zijlstra
286*2d24dd57SPeter Zijlstra /**
287*2d24dd57SPeter Zijlstra * rb_find_first() - find the first @key in @tree
288*2d24dd57SPeter Zijlstra * @key: key to match
289*2d24dd57SPeter Zijlstra * @tree: tree to search
290*2d24dd57SPeter Zijlstra * @cmp: operator defining node order
291*2d24dd57SPeter Zijlstra *
292*2d24dd57SPeter Zijlstra * Returns the leftmost node matching @key, or NULL.
293*2d24dd57SPeter Zijlstra */
294*2d24dd57SPeter Zijlstra static __always_inline struct rb_node *
rb_find_first(const void * key,const struct rb_root * tree,int (* cmp)(const void * key,const struct rb_node *))295*2d24dd57SPeter Zijlstra rb_find_first(const void *key, const struct rb_root *tree,
296*2d24dd57SPeter Zijlstra int (*cmp)(const void *key, const struct rb_node *))
297*2d24dd57SPeter Zijlstra {
298*2d24dd57SPeter Zijlstra struct rb_node *node = tree->rb_node;
299*2d24dd57SPeter Zijlstra struct rb_node *match = NULL;
300*2d24dd57SPeter Zijlstra
301*2d24dd57SPeter Zijlstra while (node) {
302*2d24dd57SPeter Zijlstra int c = cmp(key, node);
303*2d24dd57SPeter Zijlstra
304*2d24dd57SPeter Zijlstra if (c <= 0) {
305*2d24dd57SPeter Zijlstra if (!c)
306*2d24dd57SPeter Zijlstra match = node;
307*2d24dd57SPeter Zijlstra node = node->rb_left;
308*2d24dd57SPeter Zijlstra } else if (c > 0) {
309*2d24dd57SPeter Zijlstra node = node->rb_right;
310*2d24dd57SPeter Zijlstra }
311*2d24dd57SPeter Zijlstra }
312*2d24dd57SPeter Zijlstra
313*2d24dd57SPeter Zijlstra return match;
314*2d24dd57SPeter Zijlstra }
315*2d24dd57SPeter Zijlstra
316*2d24dd57SPeter Zijlstra /**
317*2d24dd57SPeter Zijlstra * rb_next_match() - find the next @key in @tree
318*2d24dd57SPeter Zijlstra * @key: key to match
319*2d24dd57SPeter Zijlstra * @tree: tree to search
320*2d24dd57SPeter Zijlstra * @cmp: operator defining node order
321*2d24dd57SPeter Zijlstra *
322*2d24dd57SPeter Zijlstra * Returns the next node matching @key, or NULL.
323*2d24dd57SPeter Zijlstra */
324*2d24dd57SPeter Zijlstra static __always_inline struct rb_node *
rb_next_match(const void * key,struct rb_node * node,int (* cmp)(const void * key,const struct rb_node *))325*2d24dd57SPeter Zijlstra rb_next_match(const void *key, struct rb_node *node,
326*2d24dd57SPeter Zijlstra int (*cmp)(const void *key, const struct rb_node *))
327*2d24dd57SPeter Zijlstra {
328*2d24dd57SPeter Zijlstra node = rb_next(node);
329*2d24dd57SPeter Zijlstra if (node && cmp(key, node))
330*2d24dd57SPeter Zijlstra node = NULL;
331*2d24dd57SPeter Zijlstra return node;
332*2d24dd57SPeter Zijlstra }
333*2d24dd57SPeter Zijlstra
334*2d24dd57SPeter Zijlstra /**
335*2d24dd57SPeter Zijlstra * rb_for_each() - iterates a subtree matching @key
336*2d24dd57SPeter Zijlstra * @node: iterator
337*2d24dd57SPeter Zijlstra * @key: key to match
338*2d24dd57SPeter Zijlstra * @tree: tree to search
339*2d24dd57SPeter Zijlstra * @cmp: operator defining node order
340*2d24dd57SPeter Zijlstra */
341*2d24dd57SPeter Zijlstra #define rb_for_each(node, key, tree, cmp) \
342*2d24dd57SPeter Zijlstra for ((node) = rb_find_first((key), (tree), (cmp)); \
343*2d24dd57SPeter Zijlstra (node); (node) = rb_next_match((key), (node), (cmp)))
344*2d24dd57SPeter Zijlstra
34503da23a3SArnaldo Carvalho de Melo #endif /* __TOOLS_LINUX_PERF_RBTREE_H */
346