| 
									
										
										
										
											2007-02-10 01:46:20 -08:00
										 |  |  | Red-black Trees (rbtree) in Linux | 
					
						
							|  |  |  | January 18, 2007 | 
					
						
							|  |  |  | Rob Landley <rob@landley.net> | 
					
						
							|  |  |  | ============================= | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | What are red-black trees, and what are they for? | 
					
						
							|  |  |  | ------------------------------------------------ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Red-black trees are a type of self-balancing binary search tree, used for | 
					
						
							|  |  |  | storing sortable key/value data pairs.  This differs from radix trees (which | 
					
						
							|  |  |  | are used to efficiently store sparse arrays and thus use long integer indexes | 
					
						
							|  |  |  | to insert/access/delete nodes) and hash tables (which are not kept sorted to | 
					
						
							|  |  |  | be easily traversed in order, and must be tuned for a specific size and | 
					
						
							|  |  |  | hash function where rbtrees scale gracefully storing arbitrary keys). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Red-black trees are similar to AVL trees, but provide faster real-time bounded | 
					
						
							|  |  |  | worst case performance for insertion and deletion (at most two rotations and | 
					
						
							|  |  |  | three rotations, respectively, to balance the tree), with slightly slower | 
					
						
							|  |  |  | (but still O(log n)) lookup time. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | To quote Linux Weekly News: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     There are a number of red-black trees in use in the kernel. | 
					
						
							| 
									
										
										
										
											2010-11-11 12:09:59 +01:00
										 |  |  |     The deadline and CFQ I/O schedulers employ rbtrees to | 
					
						
							|  |  |  |     track requests; the packet CD/DVD driver does the same. | 
					
						
							| 
									
										
										
										
											2007-02-10 01:46:20 -08:00
										 |  |  |     The high-resolution timer code uses an rbtree to organize outstanding | 
					
						
							|  |  |  |     timer requests.  The ext3 filesystem tracks directory entries in a | 
					
						
							|  |  |  |     red-black tree.  Virtual memory areas (VMAs) are tracked with red-black | 
					
						
							|  |  |  |     trees, as are epoll file descriptors, cryptographic keys, and network | 
					
						
							|  |  |  |     packets in the "hierarchical token bucket" scheduler. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This document covers use of the Linux rbtree implementation.  For more | 
					
						
							|  |  |  | information on the nature and implementation of Red Black Trees,  see: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Linux Weekly News article on red-black trees | 
					
						
							|  |  |  |     http://lwn.net/Articles/184495/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Wikipedia entry on red-black trees | 
					
						
							|  |  |  |     http://en.wikipedia.org/wiki/Red-black_tree | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Linux implementation of red-black trees | 
					
						
							|  |  |  | --------------------------------------- | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Linux's rbtree implementation lives in the file "lib/rbtree.c".  To use it, | 
					
						
							|  |  |  | "#include <linux/rbtree.h>". | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The Linux rbtree implementation is optimized for speed, and thus has one | 
					
						
							|  |  |  | less layer of indirection (and better cache locality) than more traditional | 
					
						
							|  |  |  | tree implementations.  Instead of using pointers to separate rb_node and data | 
					
						
							|  |  |  | structures, each instance of struct rb_node is embedded in the data structure | 
					
						
							|  |  |  | it organizes.  And instead of using a comparison callback function pointer, | 
					
						
							|  |  |  | users are expected to write their own tree search and insert functions | 
					
						
							|  |  |  | which call the provided rbtree functions.  Locking is also left up to the | 
					
						
							|  |  |  | user of the rbtree code. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Creating a new rbtree | 
					
						
							|  |  |  | --------------------- | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Data nodes in an rbtree tree are structures containing a struct rb_node member: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   struct mytype { | 
					
						
							|  |  |  |   	struct rb_node node; | 
					
						
							|  |  |  |   	char *keystring; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | When dealing with a pointer to the embedded struct rb_node, the containing data | 
					
						
							|  |  |  | structure may be accessed with the standard container_of() macro.  In addition, | 
					
						
							|  |  |  | individual members may be accessed directly via rb_entry(node, type, member). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | At the root of each rbtree is an rb_root structure, which is initialized to be | 
					
						
							|  |  |  | empty via: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   struct rb_root mytree = RB_ROOT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Searching for a value in an rbtree | 
					
						
							|  |  |  | ---------------------------------- | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Writing a search function for your tree is fairly straightforward: start at the | 
					
						
							|  |  |  | root, compare each value, and follow the left or right branch as necessary. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Example: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   struct mytype *my_search(struct rb_root *root, char *string) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |   	struct rb_node *node = root->rb_node; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   	while (node) { | 
					
						
							|  |  |  |   		struct mytype *data = container_of(node, struct mytype, node); | 
					
						
							|  |  |  | 		int result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		result = strcmp(string, data->keystring); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (result < 0) | 
					
						
							|  |  |  |   			node = node->rb_left; | 
					
						
							|  |  |  | 		else if (result > 0) | 
					
						
							|  |  |  |   			node = node->rb_right; | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  |   			return data; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Inserting data into an rbtree | 
					
						
							|  |  |  | ----------------------------- | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Inserting data in the tree involves first searching for the place to insert the | 
					
						
							|  |  |  | new node, then inserting the node and rebalancing ("recoloring") the tree. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The search for insertion differs from the previous search by finding the | 
					
						
							|  |  |  | location of the pointer on which to graft the new node.  The new node also | 
					
						
							|  |  |  | needs a link to its parent node for rebalancing purposes. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Example: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   int my_insert(struct rb_root *root, struct mytype *data) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |   	struct rb_node **new = &(root->rb_node), *parent = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   	/* Figure out where to put new node */ | 
					
						
							|  |  |  |   	while (*new) { | 
					
						
							|  |  |  |   		struct mytype *this = container_of(*new, struct mytype, node); | 
					
						
							|  |  |  |   		int result = strcmp(data->keystring, this->keystring); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		parent = *new; | 
					
						
							|  |  |  |   		if (result < 0) | 
					
						
							|  |  |  |   			new = &((*new)->rb_left); | 
					
						
							|  |  |  |   		else if (result > 0) | 
					
						
							|  |  |  |   			new = &((*new)->rb_right); | 
					
						
							|  |  |  |   		else | 
					
						
							|  |  |  |   			return FALSE; | 
					
						
							|  |  |  |   	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   	/* Add new node and rebalance tree. */ | 
					
						
							| 
									
										
										
										
											2009-04-17 10:58:48 +08:00
										 |  |  |   	rb_link_node(&data->node, parent, new); | 
					
						
							|  |  |  |   	rb_insert_color(&data->node, root); | 
					
						
							| 
									
										
										
										
											2007-02-10 01:46:20 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return TRUE; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Removing or replacing existing data in an rbtree | 
					
						
							|  |  |  | ------------------------------------------------ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | To remove an existing node from a tree, call: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void rb_erase(struct rb_node *victim, struct rb_root *tree); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Example: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-17 10:58:48 +08:00
										 |  |  |   struct mytype *data = mysearch(&mytree, "walrus"); | 
					
						
							| 
									
										
										
										
											2007-02-10 01:46:20 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (data) { | 
					
						
							| 
									
										
										
										
											2009-04-17 10:58:48 +08:00
										 |  |  |   	rb_erase(&data->node, &mytree); | 
					
						
							| 
									
										
										
										
											2007-02-10 01:46:20 -08:00
										 |  |  |   	myfree(data); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | To replace an existing node in a tree with a new one with the same key, call: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void rb_replace_node(struct rb_node *old, struct rb_node *new, | 
					
						
							|  |  |  |   			struct rb_root *tree); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Replacing a node this way does not re-sort the tree: If the new node doesn't | 
					
						
							|  |  |  | have the same key as the old node, the rbtree will probably become corrupted. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Iterating through the elements stored in an rbtree (in sort order) | 
					
						
							|  |  |  | ------------------------------------------------------------------ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Four functions are provided for iterating through an rbtree's contents in | 
					
						
							|  |  |  | sorted order.  These work on arbitrary trees, and should not need to be | 
					
						
							|  |  |  | modified or wrapped (except for locking purposes): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   struct rb_node *rb_first(struct rb_root *tree); | 
					
						
							|  |  |  |   struct rb_node *rb_last(struct rb_root *tree); | 
					
						
							|  |  |  |   struct rb_node *rb_next(struct rb_node *node); | 
					
						
							|  |  |  |   struct rb_node *rb_prev(struct rb_node *node); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | To start iterating, call rb_first() or rb_last() with a pointer to the root | 
					
						
							|  |  |  | of the tree, which will return a pointer to the node structure contained in | 
					
						
							|  |  |  | the first or last element in the tree.  To continue, fetch the next or previous | 
					
						
							|  |  |  | node by calling rb_next() or rb_prev() on the current node.  This will return | 
					
						
							|  |  |  | NULL when there are no more nodes left. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The iterator functions return a pointer to the embedded struct rb_node, from | 
					
						
							|  |  |  | which the containing data structure may be accessed with the container_of() | 
					
						
							|  |  |  | macro, and individual members may be accessed directly via | 
					
						
							|  |  |  | rb_entry(node, type, member). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Example: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   struct rb_node *node; | 
					
						
							|  |  |  |   for (node = rb_first(&mytree); node; node = rb_next(node)) | 
					
						
							| 
									
										
										
										
											2009-05-14 11:00:20 +02:00
										 |  |  | 	printk("key=%s\n", rb_entry(node, struct mytype, node)->keystring); | 
					
						
							| 
									
										
										
										
											2007-02-10 01:46:20 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-10 15:23:44 -08:00
										 |  |  | Support for Augmented rbtrees | 
					
						
							|  |  |  | ----------------------------- | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-08 16:31:17 -07:00
										 |  |  | Augmented rbtree is an rbtree with "some" additional data stored in | 
					
						
							|  |  |  | each node, where the additional data for node N must be a function of | 
					
						
							|  |  |  | the contents of all nodes in the subtree rooted at N. This data can | 
					
						
							|  |  |  | be used to augment some new functionality to rbtree. Augmented rbtree | 
					
						
							|  |  |  | is an optional feature built on top of basic rbtree infrastructure. | 
					
						
							|  |  |  | An rbtree user who wants this feature will have to call the augmentation | 
					
						
							|  |  |  | functions with the user provided augmentation callback when inserting | 
					
						
							|  |  |  | and erasing nodes. | 
					
						
							| 
									
										
										
										
											2011-07-24 11:23:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-08 16:31:33 -07:00
										 |  |  | C files implementing augmented rbtree manipulation must include | 
					
						
							|  |  |  | <linux/rbtree_augmented.h> instead of <linus/rbtree.h>. Note that | 
					
						
							|  |  |  | linux/rbtree_augmented.h exposes some rbtree implementations details | 
					
						
							|  |  |  | you are not expected to rely on; please stick to the documented APIs | 
					
						
							|  |  |  | there and do not include <linux/rbtree_augmented.h> from header files | 
					
						
							|  |  |  | either so as to minimize chances of your users accidentally relying on | 
					
						
							|  |  |  | such implementation details. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-08 16:31:17 -07:00
										 |  |  | On insertion, the user must update the augmented information on the path | 
					
						
							|  |  |  | leading to the inserted node, then call rb_link_node() as usual and | 
					
						
							|  |  |  | rb_augment_inserted() instead of the usual rb_insert_color() call. | 
					
						
							|  |  |  | If rb_augment_inserted() rebalances the rbtree, it will callback into | 
					
						
							|  |  |  | a user provided function to update the augmented information on the | 
					
						
							|  |  |  | affected subtrees. | 
					
						
							| 
									
										
										
										
											2011-07-24 11:23:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-08 16:31:17 -07:00
										 |  |  | When erasing a node, the user must call rb_erase_augmented() instead of | 
					
						
							|  |  |  | rb_erase(). rb_erase_augmented() calls back into user provided functions | 
					
						
							|  |  |  | to updated the augmented information on affected subtrees. | 
					
						
							| 
									
										
										
										
											2010-02-10 15:23:44 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-08 16:31:17 -07:00
										 |  |  | In both cases, the callbacks are provided through struct rb_augment_callbacks. | 
					
						
							|  |  |  | 3 callbacks must be defined: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | - A propagation callback, which updates the augmented value for a given | 
					
						
							|  |  |  |   node and its ancestors, up to a given stop point (or NULL to update | 
					
						
							|  |  |  |   all the way to the root). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | - A copy callback, which copies the augmented value for a given subtree | 
					
						
							|  |  |  |   to a newly assigned subtree root. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | - A tree rotation callback, which copies the augmented value for a given | 
					
						
							|  |  |  |   subtree to a newly assigned subtree root AND recomputes the augmented | 
					
						
							|  |  |  |   information for the former subtree root. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-08 16:31:33 -07:00
										 |  |  | The compiled code for rb_erase_augmented() may inline the propagation and | 
					
						
							|  |  |  | copy callbacks, which results in a large function, so each augmented rbtree | 
					
						
							|  |  |  | user should have a single rb_erase_augmented() call site in order to limit | 
					
						
							|  |  |  | compiled code size. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-08 16:31:17 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | Sample usage: | 
					
						
							| 
									
										
										
										
											2010-02-10 15:23:44 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | Interval tree is an example of augmented rb tree. Reference - | 
					
						
							|  |  |  | "Introduction to Algorithms" by Cormen, Leiserson, Rivest and Stein. | 
					
						
							|  |  |  | More details about interval trees: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Classical rbtree has a single key and it cannot be directly used to store | 
					
						
							|  |  |  | interval ranges like [lo:hi] and do a quick lookup for any overlap with a new | 
					
						
							|  |  |  | lo:hi or to find whether there is an exact match for a new lo:hi. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | However, rbtree can be augmented to store such interval ranges in a structured | 
					
						
							|  |  |  | way making it possible to do efficient lookup and exact match. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This "extra information" stored in each node is the maximum hi | 
					
						
							|  |  |  | (max_hi) value among all the nodes that are its descendents. This | 
					
						
							|  |  |  | information can be maintained at each node just be looking at the node | 
					
						
							|  |  |  | and its immediate children. And this will be used in O(log n) lookup | 
					
						
							|  |  |  | for lowest match (lowest start address among all possible matches) | 
					
						
							|  |  |  | with something like: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-08 16:31:17 -07:00
										 |  |  | struct interval_tree_node * | 
					
						
							|  |  |  | interval_tree_first_match(struct rb_root *root, | 
					
						
							|  |  |  | 			  unsigned long start, unsigned long last) | 
					
						
							| 
									
										
										
										
											2010-02-10 15:23:44 -08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-10-08 16:31:17 -07:00
										 |  |  | 	struct interval_tree_node *node; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!root->rb_node) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	node = rb_entry(root->rb_node, struct interval_tree_node, rb); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (true) { | 
					
						
							|  |  |  | 		if (node->rb.rb_left) { | 
					
						
							|  |  |  | 			struct interval_tree_node *left = | 
					
						
							|  |  |  | 				rb_entry(node->rb.rb_left, | 
					
						
							|  |  |  | 					 struct interval_tree_node, rb); | 
					
						
							|  |  |  | 			if (left->__subtree_last >= start) { | 
					
						
							|  |  |  | 				/* | 
					
						
							|  |  |  | 				 * Some nodes in left subtree satisfy Cond2. | 
					
						
							|  |  |  | 				 * Iterate to find the leftmost such node N. | 
					
						
							|  |  |  | 				 * If it also satisfies Cond1, that's the match | 
					
						
							|  |  |  | 				 * we are looking for. Otherwise, there is no | 
					
						
							|  |  |  | 				 * matching interval as nodes to the right of N | 
					
						
							|  |  |  | 				 * can't satisfy Cond1 either. | 
					
						
							|  |  |  | 				 */ | 
					
						
							|  |  |  | 				node = left; | 
					
						
							|  |  |  | 				continue; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2010-02-10 15:23:44 -08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-10-08 16:31:17 -07:00
										 |  |  | 		if (node->start <= last) {		/* Cond1 */ | 
					
						
							|  |  |  | 			if (node->last >= start)	/* Cond2 */ | 
					
						
							|  |  |  | 				return node;	/* node is leftmost match */ | 
					
						
							|  |  |  | 			if (node->rb.rb_right) { | 
					
						
							|  |  |  | 				node = rb_entry(node->rb.rb_right, | 
					
						
							|  |  |  | 					struct interval_tree_node, rb); | 
					
						
							|  |  |  | 				if (node->__subtree_last >= start) | 
					
						
							|  |  |  | 					continue; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return NULL;	/* No match */ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Insertion/removal are defined using the following augmented callbacks: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline unsigned long | 
					
						
							|  |  |  | compute_subtree_last(struct interval_tree_node *node) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned long max = node->last, subtree_last; | 
					
						
							|  |  |  | 	if (node->rb.rb_left) { | 
					
						
							|  |  |  | 		subtree_last = rb_entry(node->rb.rb_left, | 
					
						
							|  |  |  | 			struct interval_tree_node, rb)->__subtree_last; | 
					
						
							|  |  |  | 		if (max < subtree_last) | 
					
						
							|  |  |  | 			max = subtree_last; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (node->rb.rb_right) { | 
					
						
							|  |  |  | 		subtree_last = rb_entry(node->rb.rb_right, | 
					
						
							|  |  |  | 			struct interval_tree_node, rb)->__subtree_last; | 
					
						
							|  |  |  | 		if (max < subtree_last) | 
					
						
							|  |  |  | 			max = subtree_last; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return max; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void augment_propagate(struct rb_node *rb, struct rb_node *stop) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	while (rb != stop) { | 
					
						
							|  |  |  | 		struct interval_tree_node *node = | 
					
						
							|  |  |  | 			rb_entry(rb, struct interval_tree_node, rb); | 
					
						
							|  |  |  | 		unsigned long subtree_last = compute_subtree_last(node); | 
					
						
							|  |  |  | 		if (node->__subtree_last == subtree_last) | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		node->__subtree_last = subtree_last; | 
					
						
							|  |  |  | 		rb = rb_parent(&node->rb); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void augment_copy(struct rb_node *rb_old, struct rb_node *rb_new) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct interval_tree_node *old = | 
					
						
							|  |  |  | 		rb_entry(rb_old, struct interval_tree_node, rb); | 
					
						
							|  |  |  | 	struct interval_tree_node *new = | 
					
						
							|  |  |  | 		rb_entry(rb_new, struct interval_tree_node, rb); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	new->__subtree_last = old->__subtree_last; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void augment_rotate(struct rb_node *rb_old, struct rb_node *rb_new) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct interval_tree_node *old = | 
					
						
							|  |  |  | 		rb_entry(rb_old, struct interval_tree_node, rb); | 
					
						
							|  |  |  | 	struct interval_tree_node *new = | 
					
						
							|  |  |  | 		rb_entry(rb_new, struct interval_tree_node, rb); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	new->__subtree_last = old->__subtree_last; | 
					
						
							|  |  |  | 	old->__subtree_last = compute_subtree_last(old); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const struct rb_augment_callbacks augment_callbacks = { | 
					
						
							|  |  |  | 	augment_propagate, augment_copy, augment_rotate | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void interval_tree_insert(struct interval_tree_node *node, | 
					
						
							|  |  |  | 			  struct rb_root *root) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct rb_node **link = &root->rb_node, *rb_parent = NULL; | 
					
						
							|  |  |  | 	unsigned long start = node->start, last = node->last; | 
					
						
							|  |  |  | 	struct interval_tree_node *parent; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (*link) { | 
					
						
							|  |  |  | 		rb_parent = *link; | 
					
						
							|  |  |  | 		parent = rb_entry(rb_parent, struct interval_tree_node, rb); | 
					
						
							|  |  |  | 		if (parent->__subtree_last < last) | 
					
						
							|  |  |  | 			parent->__subtree_last = last; | 
					
						
							|  |  |  | 		if (start < parent->start) | 
					
						
							|  |  |  | 			link = &parent->rb.rb_left; | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			link = &parent->rb.rb_right; | 
					
						
							| 
									
										
										
										
											2010-02-10 15:23:44 -08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-10-08 16:31:17 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	node->__subtree_last = last; | 
					
						
							|  |  |  | 	rb_link_node(&node->rb, rb_parent, link); | 
					
						
							|  |  |  | 	rb_insert_augmented(&node->rb, root, &augment_callbacks); | 
					
						
							| 
									
										
										
										
											2010-02-10 15:23:44 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-08 16:31:17 -07:00
										 |  |  | void interval_tree_remove(struct interval_tree_node *node, | 
					
						
							|  |  |  | 			  struct rb_root *root) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	rb_erase_augmented(&node->rb, root, &augment_callbacks); | 
					
						
							|  |  |  | } |