rbtree_test.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. #include <linux/module.h>
  2. #include <linux/rbtree.h>
  3. #include <linux/random.h>
  4. #include <asm/timex.h>
  5. #define NODES 100
  6. #define PERF_LOOPS 100000
  7. #define CHECK_LOOPS 100
  8. struct test_node {
  9. struct rb_node rb;
  10. u32 key;
  11. };
  12. static struct rb_root root = RB_ROOT;
  13. static struct test_node nodes[NODES];
  14. static struct rnd_state rnd;
  15. static void insert(struct test_node *node, struct rb_root *root)
  16. {
  17. struct rb_node **new = &root->rb_node, *parent = NULL;
  18. while (*new) {
  19. parent = *new;
  20. if (node->key < rb_entry(parent, struct test_node, rb)->key)
  21. new = &parent->rb_left;
  22. else
  23. new = &parent->rb_right;
  24. }
  25. rb_link_node(&node->rb, parent, new);
  26. rb_insert_color(&node->rb, root);
  27. }
  28. static inline void erase(struct test_node *node, struct rb_root *root)
  29. {
  30. rb_erase(&node->rb, root);
  31. }
  32. static void init(void)
  33. {
  34. int i;
  35. for (i = 0; i < NODES; i++)
  36. nodes[i].key = prandom32(&rnd);
  37. }
  38. static bool is_red(struct rb_node *rb)
  39. {
  40. return !(rb->__rb_parent_color & 1);
  41. }
  42. static int black_path_count(struct rb_node *rb)
  43. {
  44. int count;
  45. for (count = 0; rb; rb = rb_parent(rb))
  46. count += !is_red(rb);
  47. return count;
  48. }
  49. static void check(int nr_nodes)
  50. {
  51. struct rb_node *rb;
  52. int count = 0;
  53. int blacks;
  54. u32 prev_key = 0;
  55. for (rb = rb_first(&root); rb; rb = rb_next(rb)) {
  56. struct test_node *node = rb_entry(rb, struct test_node, rb);
  57. WARN_ON_ONCE(node->key < prev_key);
  58. WARN_ON_ONCE(is_red(rb) &&
  59. (!rb_parent(rb) || is_red(rb_parent(rb))));
  60. if (!count)
  61. blacks = black_path_count(rb);
  62. else
  63. WARN_ON_ONCE((!rb->rb_left || !rb->rb_right) &&
  64. blacks != black_path_count(rb));
  65. prev_key = node->key;
  66. count++;
  67. }
  68. WARN_ON_ONCE(count != nr_nodes);
  69. }
  70. static int rbtree_test_init(void)
  71. {
  72. int i, j;
  73. cycles_t time1, time2, time;
  74. printk(KERN_ALERT "rbtree testing");
  75. prandom32_seed(&rnd, 3141592653589793238ULL);
  76. init();
  77. time1 = get_cycles();
  78. for (i = 0; i < PERF_LOOPS; i++) {
  79. for (j = 0; j < NODES; j++)
  80. insert(nodes + j, &root);
  81. for (j = 0; j < NODES; j++)
  82. erase(nodes + j, &root);
  83. }
  84. time2 = get_cycles();
  85. time = time2 - time1;
  86. time = div_u64(time, PERF_LOOPS);
  87. printk(" -> %llu cycles\n", (unsigned long long)time);
  88. for (i = 0; i < CHECK_LOOPS; i++) {
  89. init();
  90. for (j = 0; j < NODES; j++) {
  91. check(j);
  92. insert(nodes + j, &root);
  93. }
  94. for (j = 0; j < NODES; j++) {
  95. check(NODES - j);
  96. erase(nodes + j, &root);
  97. }
  98. check(0);
  99. }
  100. return -EAGAIN; /* Fail will directly unload the module */
  101. }
  102. static void rbtree_test_exit(void)
  103. {
  104. printk(KERN_ALERT "test exit\n");
  105. }
  106. module_init(rbtree_test_init)
  107. module_exit(rbtree_test_exit)
  108. MODULE_LICENSE("GPL");
  109. MODULE_AUTHOR("Michel Lespinasse");
  110. MODULE_DESCRIPTION("Red Black Tree test");