avl_adpt.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-11-14 WangXiaoyao the first version
  9. */
  10. #include <rtdef.h>
  11. #include <avl.h>
  12. #include "avl_adpt.h"
  13. #include "mm_aspace.h"
  14. #include "mm_private.h"
  15. #define DBG_TAG "MM"
  16. #define DBG_LVL DBG_INFO
  17. #include <rtdbg.h>
  18. /**
  19. * @brief Adapter Layer for lwp AVL BST
  20. */
  21. rt_err_t _aspace_bst_init(struct rt_aspace *aspace)
  22. {
  23. aspace->tree.tree.root_node = AVL_ROOT;
  24. return RT_EOK;
  25. }
  26. static int compare_overlap(void *as, void *ae, void *bs, void *be)
  27. {
  28. LOG_D("as %lx, ae %lx, bs %lx, be %lx", as, ae, bs, be);
  29. int cmp;
  30. if (as > be)
  31. {
  32. cmp = 1;
  33. }
  34. else if (ae < bs)
  35. {
  36. cmp = -1;
  37. }
  38. else
  39. {
  40. cmp = 0;
  41. }
  42. LOG_D("ret %d", cmp);
  43. return cmp;
  44. }
  45. static int compare_exceed(void *as, void *ae, void *bs, void *be)
  46. {
  47. LOG_D("as %lx, ae %lx, bs %lx, be %lx", as, ae, bs, be);
  48. int cmp;
  49. if (as > bs)
  50. {
  51. cmp = 1;
  52. }
  53. else if (as < bs)
  54. {
  55. cmp = -1;
  56. }
  57. else
  58. {
  59. cmp = 0;
  60. }
  61. LOG_D("ret %d", cmp);
  62. return cmp;
  63. }
  64. static struct rt_varea *search(struct util_avl_root *root,
  65. struct _mm_range range,
  66. int (*compare)(void *as, void *ae, void *bs,
  67. void *be))
  68. {
  69. struct util_avl_struct *node = root->root_node;
  70. while (node)
  71. {
  72. rt_varea_t varea = VAREA_ENTRY(node);
  73. int cmp = compare(range.start, range.end, varea->start,
  74. varea->start + varea->size - 1);
  75. if (cmp < 0)
  76. {
  77. node = node->avl_left;
  78. }
  79. else if (cmp > 0)
  80. {
  81. node = node->avl_right;
  82. }
  83. else
  84. {
  85. return varea;
  86. }
  87. }
  88. return NULL;
  89. }
  90. struct rt_varea *_aspace_bst_search(struct rt_aspace *aspace, void *key)
  91. {
  92. struct util_avl_root *root = &aspace->tree.tree;
  93. struct _mm_range range = {key, key};
  94. return search(root, range, compare_overlap);
  95. }
  96. rt_varea_t _aspace_bst_search_exceed(struct rt_aspace *aspace, void *start)
  97. {
  98. struct util_avl_root *root = &aspace->tree.tree;
  99. struct util_avl_struct *node = root->root_node;
  100. rt_varea_t closest = NULL;
  101. ptrdiff_t min_off = PTRDIFF_MAX;
  102. while (node)
  103. {
  104. rt_varea_t varea = VAREA_ENTRY(node);
  105. void *va_s = varea->start;
  106. int cmp = compare_exceed(start, start, va_s, va_s);
  107. if (cmp < 0)
  108. {
  109. ptrdiff_t off = va_s - start;
  110. if (off < min_off)
  111. {
  112. min_off = off;
  113. closest = varea;
  114. }
  115. node = node->avl_left;
  116. }
  117. else if (cmp > 0)
  118. {
  119. node = node->avl_right;
  120. }
  121. else
  122. {
  123. return varea;
  124. }
  125. }
  126. return closest;
  127. }
  128. struct rt_varea *_aspace_bst_search_overlap(struct rt_aspace *aspace,
  129. struct _mm_range range)
  130. {
  131. struct util_avl_root *root = &aspace->tree.tree;
  132. return search(root, range, compare_overlap);
  133. }
  134. void _aspace_bst_insert(struct rt_aspace *aspace, struct rt_varea *varea)
  135. {
  136. struct util_avl_root *root = &aspace->tree.tree;
  137. struct util_avl_struct *current = NULL;
  138. struct util_avl_struct **next = &(root->root_node);
  139. rt_ubase_t key = (rt_ubase_t)varea->start;
  140. /* Figure out where to put new node */
  141. while (*next)
  142. {
  143. current = *next;
  144. struct rt_varea *data = VAREA_ENTRY(current);
  145. if (key < (rt_ubase_t)data->start)
  146. next = &(current->avl_left);
  147. else if (key > (rt_ubase_t)data->start)
  148. next = &(current->avl_right);
  149. else
  150. return;
  151. }
  152. /* Add new node and rebalance tree. */
  153. util_avl_link(&varea->node.node, current, next);
  154. util_avl_rebalance(current, root);
  155. return;
  156. }
  157. void _aspace_bst_remove(struct rt_aspace *aspace, struct rt_varea *varea)
  158. {
  159. struct util_avl_struct *node = &varea->node.node;
  160. util_avl_remove(node, &aspace->tree.tree);
  161. }