rbtree.h 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /*
  2. Red Black Trees
  3. (C) 1999 Andrea Arcangeli <andrea@suse.de>
  4. * SPDX-License-Identifier: GPL-2.0+
  5. linux/include/linux/rbtree.h
  6. To use rbtrees you'll have to implement your own insert and search cores.
  7. This will avoid us to use callbacks and to drop drammatically performances.
  8. I know it's not the cleaner way, but in C (not in C++) to get
  9. performances and genericity...
  10. Some example of insert and search follows here. The search is a plain
  11. normal search over an ordered tree. The insert instead must be implemented
  12. int two steps: as first thing the code must insert the element in
  13. order as a red leaf in the tree, then the support library function
  14. rb_insert_color() must be called. Such function will do the
  15. not trivial work to rebalance the rbtree if necessary.
  16. -----------------------------------------------------------------------
  17. static inline struct page * rb_search_page_cache(struct inode * inode,
  18. unsigned long offset)
  19. {
  20. struct rb_node * n = inode->i_rb_page_cache.rb_node;
  21. struct page * page;
  22. while (n)
  23. {
  24. page = rb_entry(n, struct page, rb_page_cache);
  25. if (offset < page->offset)
  26. n = n->rb_left;
  27. else if (offset > page->offset)
  28. n = n->rb_right;
  29. else
  30. return page;
  31. }
  32. return NULL;
  33. }
  34. static inline struct page * __rb_insert_page_cache(struct inode * inode,
  35. unsigned long offset,
  36. struct rb_node * node)
  37. {
  38. struct rb_node ** p = &inode->i_rb_page_cache.rb_node;
  39. struct rb_node * parent = NULL;
  40. struct page * page;
  41. while (*p)
  42. {
  43. parent = *p;
  44. page = rb_entry(parent, struct page, rb_page_cache);
  45. if (offset < page->offset)
  46. p = &(*p)->rb_left;
  47. else if (offset > page->offset)
  48. p = &(*p)->rb_right;
  49. else
  50. return page;
  51. }
  52. rb_link_node(node, parent, p);
  53. return NULL;
  54. }
  55. static inline struct page * rb_insert_page_cache(struct inode * inode,
  56. unsigned long offset,
  57. struct rb_node * node)
  58. {
  59. struct page * ret;
  60. if ((ret = __rb_insert_page_cache(inode, offset, node)))
  61. goto out;
  62. rb_insert_color(node, &inode->i_rb_page_cache);
  63. out:
  64. return ret;
  65. }
  66. -----------------------------------------------------------------------
  67. */
  68. #ifndef _LINUX_RBTREE_H
  69. #define _LINUX_RBTREE_H
  70. #include <linux/stddef.h>
  71. struct rb_node
  72. {
  73. unsigned long rb_parent_color;
  74. #define RB_RED 0
  75. #define RB_BLACK 1
  76. struct rb_node *rb_right;
  77. struct rb_node *rb_left;
  78. } __attribute__((aligned(sizeof(long))));
  79. /* The alignment might seem pointless, but allegedly CRIS needs it */
  80. struct rb_root
  81. {
  82. struct rb_node *rb_node;
  83. };
  84. #define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3))
  85. #define rb_color(r) ((r)->rb_parent_color & 1)
  86. #define rb_is_red(r) (!rb_color(r))
  87. #define rb_is_black(r) rb_color(r)
  88. #define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0)
  89. #define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0)
  90. static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
  91. {
  92. rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p;
  93. }
  94. static inline void rb_set_color(struct rb_node *rb, int color)
  95. {
  96. rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
  97. }
  98. #define RB_ROOT (struct rb_root) { NULL, }
  99. #define rb_entry(ptr, type, member) container_of(ptr, type, member)
  100. #define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL)
  101. #define RB_EMPTY_NODE(node) (rb_parent(node) == node)
  102. #define RB_CLEAR_NODE(node) (rb_set_parent(node, node))
  103. extern void rb_insert_color(struct rb_node *, struct rb_root *);
  104. extern void rb_erase(struct rb_node *, struct rb_root *);
  105. /* Find logical next and previous nodes in a tree */
  106. extern struct rb_node *rb_next(struct rb_node *);
  107. extern struct rb_node *rb_prev(struct rb_node *);
  108. extern struct rb_node *rb_first(struct rb_root *);
  109. extern struct rb_node *rb_last(struct rb_root *);
  110. /* Fast replacement of a single node without remove/rebalance/add/rebalance */
  111. extern void rb_replace_node(struct rb_node *victim, struct rb_node *new,
  112. struct rb_root *root);
  113. static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
  114. struct rb_node ** rb_link)
  115. {
  116. node->rb_parent_color = (unsigned long )parent;
  117. node->rb_left = node->rb_right = NULL;
  118. *rb_link = node;
  119. }
  120. #endif /* _LINUX_RBTREE_H */