avl_adpt.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  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. (char *)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. /* varae exceed start */
  110. ptrdiff_t off = (char *)va_s - (char *)start;
  111. if (off < min_off)
  112. {
  113. min_off = off;
  114. closest = varea;
  115. }
  116. node = node->avl_left;
  117. }
  118. else if (cmp > 0)
  119. {
  120. /* find the next huger varea */
  121. node = node->avl_right;
  122. }
  123. else
  124. {
  125. return varea;
  126. }
  127. }
  128. return closest;
  129. }
  130. struct rt_varea *_aspace_bst_search_overlap(struct rt_aspace *aspace,
  131. struct _mm_range range)
  132. {
  133. struct util_avl_root *root = &aspace->tree.tree;
  134. return search(root, range, compare_overlap);
  135. }
  136. void _aspace_bst_insert(struct rt_aspace *aspace, struct rt_varea *varea)
  137. {
  138. struct util_avl_root *root = &aspace->tree.tree;
  139. struct util_avl_struct *current = NULL;
  140. struct util_avl_struct **next = &(root->root_node);
  141. rt_ubase_t key = (rt_ubase_t)varea->start;
  142. /* Figure out where to put new node */
  143. while (*next)
  144. {
  145. current = *next;
  146. struct rt_varea *data = VAREA_ENTRY(current);
  147. if (key < (rt_ubase_t)data->start)
  148. next = &(current->avl_left);
  149. else if (key > (rt_ubase_t)data->start)
  150. next = &(current->avl_right);
  151. else
  152. return;
  153. }
  154. /* Add new node and rebalance tree. */
  155. util_avl_link(&varea->node.node, current, next);
  156. util_avl_rebalance(current, root);
  157. return;
  158. }
  159. void _aspace_bst_remove(struct rt_aspace *aspace, struct rt_varea *varea)
  160. {
  161. struct util_avl_struct *node = &varea->node.node;
  162. util_avl_remove(node, &aspace->tree.tree);
  163. }