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