rbtree_i.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /*
  2. * Copyright (c) 2010, 2011 Richard Braun.
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  15. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  16. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  17. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  18. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  19. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  20. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  21. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  23. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. #ifndef _KERN_RBTREE_I_H
  26. #define _KERN_RBTREE_I_H
  27. #include <assert.h>
  28. /** @file */
  29. /**
  30. * Red-black node structure.
  31. *
  32. * To reduce the number of branches and the instruction cache footprint,
  33. * the left and right child pointers are stored in an array, and the symmetry
  34. * of most tree operations is exploited by using left/right variables when
  35. * referring to children.
  36. *
  37. * In addition, this implementation assumes that all nodes are 4-byte aligned,
  38. * so that the least significant bit of the parent member can be used to store
  39. * the color of the node. This is true for all modern 32 and 64 bits
  40. * architectures, as long as the nodes aren't embedded in structures with
  41. * special alignment constraints such as member packing.
  42. */
  43. struct starpu_rbtree_node {
  44. uintptr_t parent;
  45. struct starpu_rbtree_node *children[2];
  46. };
  47. /**
  48. * Red-black tree structure.
  49. */
  50. struct starpu_rbtree {
  51. struct starpu_rbtree_node *root;
  52. };
  53. /**
  54. * Masks applied on the parent member of a node to obtain either the
  55. * color or the parent address.
  56. */
  57. #define STARPU_RBTREE_COLOR_MASK ((uintptr_t) 0x1)
  58. #define STARPU_RBTREE_PARENT_MASK (~((uintptr_t) 0x3))
  59. /**
  60. * Node colors.
  61. */
  62. #define STARPU_RBTREE_COLOR_RED 0
  63. #define STARPU_RBTREE_COLOR_BLACK 1
  64. /**
  65. * Masks applied on slots to obtain either the child index or the parent
  66. * address.
  67. */
  68. #define STARPU_RBTREE_SLOT_INDEX_MASK ((uintptr_t) 0x1)
  69. #define STARPU_RBTREE_SLOT_PARENT_MASK (~STARPU_RBTREE_SLOT_INDEX_MASK)
  70. /**
  71. * Return true if the given pointer is suitably aligned.
  72. */
  73. static inline int starpu_rbtree_check_alignment(const struct starpu_rbtree_node *node)
  74. {
  75. return ((uintptr_t)node & (~STARPU_RBTREE_PARENT_MASK)) == 0;
  76. }
  77. /**
  78. * Return true if the given index is a valid child index.
  79. */
  80. static inline int starpu_rbtree_check_index(int index)
  81. {
  82. return index == (index & 1);
  83. }
  84. /**
  85. * Convert the result of a comparison into an index in the children array
  86. * (0 or 1).
  87. *
  88. * This function is mostly used when looking up a node.
  89. */
  90. static inline int starpu_rbtree_d2i(int diff)
  91. {
  92. return !(diff <= 0);
  93. }
  94. /**
  95. * Return the parent of a node.
  96. */
  97. static inline struct starpu_rbtree_node * starpu_rbtree_parent(const struct starpu_rbtree_node *node)
  98. {
  99. return (struct starpu_rbtree_node *)(node->parent & STARPU_RBTREE_PARENT_MASK);
  100. }
  101. /**
  102. * Translate an insertion point into a slot.
  103. */
  104. static inline uintptr_t starpu_rbtree_slot(struct starpu_rbtree_node *parent, int index)
  105. {
  106. assert(starpu_rbtree_check_alignment(parent));
  107. assert(starpu_rbtree_check_index(index));
  108. return (uintptr_t)parent | index;
  109. }
  110. /**
  111. * Extract the parent address from a slot.
  112. */
  113. static inline struct starpu_rbtree_node * starpu_rbtree_slot_parent(uintptr_t slot)
  114. {
  115. return (struct starpu_rbtree_node *)(slot & STARPU_RBTREE_SLOT_PARENT_MASK);
  116. }
  117. /**
  118. * Extract the index from a slot.
  119. */
  120. static inline int starpu_rbtree_slot_index(uintptr_t slot)
  121. {
  122. return slot & STARPU_RBTREE_SLOT_INDEX_MASK;
  123. }
  124. /**
  125. * Insert a node in a tree, rebalancing it if necessary.
  126. *
  127. * The index parameter is the index in the children array of the parent where
  128. * the new node is to be inserted. It is ignored if the parent is null.
  129. *
  130. * This function is intended to be used by the starpu_rbtree_insert() macro only.
  131. */
  132. void starpu_rbtree_insert_rebalance(struct starpu_rbtree *tree, struct starpu_rbtree_node *parent,
  133. int index, struct starpu_rbtree_node *node);
  134. /**
  135. * Return the previous or next node relative to a location in a tree.
  136. *
  137. * The parent and index parameters define the location, which can be empty.
  138. * The direction parameter is either STARPU_RBTREE_LEFT (to obtain the previous
  139. * node) or STARPU_RBTREE_RIGHT (to obtain the next one).
  140. */
  141. struct starpu_rbtree_node * starpu_rbtree_nearest(struct starpu_rbtree_node *parent, int index,
  142. int direction);
  143. /**
  144. * Return the first or last node of a tree.
  145. *
  146. * The direction parameter is either STARPU_RBTREE_LEFT (to obtain the first node)
  147. * or STARPU_RBTREE_RIGHT (to obtain the last one).
  148. */
  149. struct starpu_rbtree_node * starpu_rbtree_firstlast(const struct starpu_rbtree *tree, int direction);
  150. /**
  151. * Return the node next to, or previous to the given node.
  152. *
  153. * The direction parameter is either STARPU_RBTREE_LEFT (to obtain the previous node)
  154. * or STARPU_RBTREE_RIGHT (to obtain the next one).
  155. */
  156. struct starpu_rbtree_node * starpu_rbtree_walk(struct starpu_rbtree_node *node, int direction);
  157. /**
  158. * Return the left-most deepest node of a tree, which is the starting point of
  159. * the postorder traversal performed by starpu_rbtree_for_each_remove().
  160. */
  161. struct starpu_rbtree_node * starpu_rbtree_postwalk_deepest(const struct starpu_rbtree *tree);
  162. /**
  163. * Unlink a node from its tree and return the next (right) node in postorder.
  164. */
  165. struct starpu_rbtree_node * starpu_rbtree_postwalk_unlink(struct starpu_rbtree_node *node);
  166. #endif /* _KERN_RBTREE_I_H */