xref: /rk3399_rockchip-uboot/include/linux/rbtree.h (revision 1a4596601fd395f3afb8f82f3f840c5e00bdd57a)
17ba890bfSKyungmin Park /*
27ba890bfSKyungmin Park   Red Black Trees
37ba890bfSKyungmin Park   (C) 1999  Andrea Arcangeli <andrea@suse.de>
47ba890bfSKyungmin Park 
5*1a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
67ba890bfSKyungmin Park 
77ba890bfSKyungmin Park   linux/include/linux/rbtree.h
87ba890bfSKyungmin Park 
97ba890bfSKyungmin Park   To use rbtrees you'll have to implement your own insert and search cores.
107ba890bfSKyungmin Park   This will avoid us to use callbacks and to drop drammatically performances.
117ba890bfSKyungmin Park   I know it's not the cleaner way,  but in C (not in C++) to get
127ba890bfSKyungmin Park   performances and genericity...
137ba890bfSKyungmin Park 
147ba890bfSKyungmin Park   Some example of insert and search follows here. The search is a plain
157ba890bfSKyungmin Park   normal search over an ordered tree. The insert instead must be implemented
167ba890bfSKyungmin Park   int two steps: as first thing the code must insert the element in
177ba890bfSKyungmin Park   order as a red leaf in the tree, then the support library function
187ba890bfSKyungmin Park   rb_insert_color() must be called. Such function will do the
197ba890bfSKyungmin Park   not trivial work to rebalance the rbtree if necessary.
207ba890bfSKyungmin Park 
217ba890bfSKyungmin Park -----------------------------------------------------------------------
227ba890bfSKyungmin Park static inline struct page * rb_search_page_cache(struct inode * inode,
237ba890bfSKyungmin Park 						 unsigned long offset)
247ba890bfSKyungmin Park {
257ba890bfSKyungmin Park 	struct rb_node * n = inode->i_rb_page_cache.rb_node;
267ba890bfSKyungmin Park 	struct page * page;
277ba890bfSKyungmin Park 
287ba890bfSKyungmin Park 	while (n)
297ba890bfSKyungmin Park 	{
307ba890bfSKyungmin Park 		page = rb_entry(n, struct page, rb_page_cache);
317ba890bfSKyungmin Park 
327ba890bfSKyungmin Park 		if (offset < page->offset)
337ba890bfSKyungmin Park 			n = n->rb_left;
347ba890bfSKyungmin Park 		else if (offset > page->offset)
357ba890bfSKyungmin Park 			n = n->rb_right;
367ba890bfSKyungmin Park 		else
377ba890bfSKyungmin Park 			return page;
387ba890bfSKyungmin Park 	}
397ba890bfSKyungmin Park 	return NULL;
407ba890bfSKyungmin Park }
417ba890bfSKyungmin Park 
427ba890bfSKyungmin Park static inline struct page * __rb_insert_page_cache(struct inode * inode,
437ba890bfSKyungmin Park 						   unsigned long offset,
447ba890bfSKyungmin Park 						   struct rb_node * node)
457ba890bfSKyungmin Park {
467ba890bfSKyungmin Park 	struct rb_node ** p = &inode->i_rb_page_cache.rb_node;
477ba890bfSKyungmin Park 	struct rb_node * parent = NULL;
487ba890bfSKyungmin Park 	struct page * page;
497ba890bfSKyungmin Park 
507ba890bfSKyungmin Park 	while (*p)
517ba890bfSKyungmin Park 	{
527ba890bfSKyungmin Park 		parent = *p;
537ba890bfSKyungmin Park 		page = rb_entry(parent, struct page, rb_page_cache);
547ba890bfSKyungmin Park 
557ba890bfSKyungmin Park 		if (offset < page->offset)
567ba890bfSKyungmin Park 			p = &(*p)->rb_left;
577ba890bfSKyungmin Park 		else if (offset > page->offset)
587ba890bfSKyungmin Park 			p = &(*p)->rb_right;
597ba890bfSKyungmin Park 		else
607ba890bfSKyungmin Park 			return page;
617ba890bfSKyungmin Park 	}
627ba890bfSKyungmin Park 
637ba890bfSKyungmin Park 	rb_link_node(node, parent, p);
647ba890bfSKyungmin Park 
657ba890bfSKyungmin Park 	return NULL;
667ba890bfSKyungmin Park }
677ba890bfSKyungmin Park 
687ba890bfSKyungmin Park static inline struct page * rb_insert_page_cache(struct inode * inode,
697ba890bfSKyungmin Park 						 unsigned long offset,
707ba890bfSKyungmin Park 						 struct rb_node * node)
717ba890bfSKyungmin Park {
727ba890bfSKyungmin Park 	struct page * ret;
737ba890bfSKyungmin Park 	if ((ret = __rb_insert_page_cache(inode, offset, node)))
747ba890bfSKyungmin Park 		goto out;
757ba890bfSKyungmin Park 	rb_insert_color(node, &inode->i_rb_page_cache);
767ba890bfSKyungmin Park  out:
777ba890bfSKyungmin Park 	return ret;
787ba890bfSKyungmin Park }
797ba890bfSKyungmin Park -----------------------------------------------------------------------
807ba890bfSKyungmin Park */
817ba890bfSKyungmin Park 
827ba890bfSKyungmin Park #ifndef	_LINUX_RBTREE_H
837ba890bfSKyungmin Park #define	_LINUX_RBTREE_H
847ba890bfSKyungmin Park 
857ba890bfSKyungmin Park #include <linux/stddef.h>
867ba890bfSKyungmin Park 
877ba890bfSKyungmin Park struct rb_node
887ba890bfSKyungmin Park {
897ba890bfSKyungmin Park 	unsigned long  rb_parent_color;
907ba890bfSKyungmin Park #define	RB_RED		0
917ba890bfSKyungmin Park #define	RB_BLACK	1
927ba890bfSKyungmin Park 	struct rb_node *rb_right;
937ba890bfSKyungmin Park 	struct rb_node *rb_left;
947ba890bfSKyungmin Park } __attribute__((aligned(sizeof(long))));
957ba890bfSKyungmin Park     /* The alignment might seem pointless, but allegedly CRIS needs it */
967ba890bfSKyungmin Park 
977ba890bfSKyungmin Park struct rb_root
987ba890bfSKyungmin Park {
997ba890bfSKyungmin Park 	struct rb_node *rb_node;
1007ba890bfSKyungmin Park };
1017ba890bfSKyungmin Park 
1027ba890bfSKyungmin Park 
1037ba890bfSKyungmin Park #define rb_parent(r)   ((struct rb_node *)((r)->rb_parent_color & ~3))
1047ba890bfSKyungmin Park #define rb_color(r)   ((r)->rb_parent_color & 1)
1057ba890bfSKyungmin Park #define rb_is_red(r)   (!rb_color(r))
1067ba890bfSKyungmin Park #define rb_is_black(r) rb_color(r)
1077ba890bfSKyungmin Park #define rb_set_red(r)  do { (r)->rb_parent_color &= ~1; } while (0)
1087ba890bfSKyungmin Park #define rb_set_black(r)  do { (r)->rb_parent_color |= 1; } while (0)
1097ba890bfSKyungmin Park 
1107ba890bfSKyungmin Park static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
1117ba890bfSKyungmin Park {
1127ba890bfSKyungmin Park 	rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p;
1137ba890bfSKyungmin Park }
1147ba890bfSKyungmin Park static inline void rb_set_color(struct rb_node *rb, int color)
1157ba890bfSKyungmin Park {
1167ba890bfSKyungmin Park 	rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
1177ba890bfSKyungmin Park }
1187ba890bfSKyungmin Park 
1197ba890bfSKyungmin Park #define RB_ROOT	(struct rb_root) { NULL, }
1207ba890bfSKyungmin Park #define	rb_entry(ptr, type, member) container_of(ptr, type, member)
1217ba890bfSKyungmin Park 
1227ba890bfSKyungmin Park #define RB_EMPTY_ROOT(root)	((root)->rb_node == NULL)
1237ba890bfSKyungmin Park #define RB_EMPTY_NODE(node)	(rb_parent(node) == node)
1247ba890bfSKyungmin Park #define RB_CLEAR_NODE(node)	(rb_set_parent(node, node))
1257ba890bfSKyungmin Park 
1267ba890bfSKyungmin Park extern void rb_insert_color(struct rb_node *, struct rb_root *);
1277ba890bfSKyungmin Park extern void rb_erase(struct rb_node *, struct rb_root *);
1287ba890bfSKyungmin Park 
1297ba890bfSKyungmin Park /* Find logical next and previous nodes in a tree */
1307ba890bfSKyungmin Park extern struct rb_node *rb_next(struct rb_node *);
1317ba890bfSKyungmin Park extern struct rb_node *rb_prev(struct rb_node *);
1327ba890bfSKyungmin Park extern struct rb_node *rb_first(struct rb_root *);
1337ba890bfSKyungmin Park extern struct rb_node *rb_last(struct rb_root *);
1347ba890bfSKyungmin Park 
1357ba890bfSKyungmin Park /* Fast replacement of a single node without remove/rebalance/add/rebalance */
1367ba890bfSKyungmin Park extern void rb_replace_node(struct rb_node *victim, struct rb_node *new,
1377ba890bfSKyungmin Park 			    struct rb_root *root);
1387ba890bfSKyungmin Park 
1397ba890bfSKyungmin Park static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
1407ba890bfSKyungmin Park 				struct rb_node ** rb_link)
1417ba890bfSKyungmin Park {
1427ba890bfSKyungmin Park 	node->rb_parent_color = (unsigned long )parent;
1437ba890bfSKyungmin Park 	node->rb_left = node->rb_right = NULL;
1447ba890bfSKyungmin Park 
1457ba890bfSKyungmin Park 	*rb_link = node;
1467ba890bfSKyungmin Park }
1477ba890bfSKyungmin Park 
1487ba890bfSKyungmin Park #endif	/* _LINUX_RBTREE_H */
149