mm_memblock_tc.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2023-09-28 zmshahaha the first version
  9. */
  10. #include <mm_memblock.h>
  11. #include "common.h"
  12. #include <rtservice.h>
  13. #define SZ_128M 0x08000000
  14. #define SZ_256M 0x10000000
  15. #define SZ_512M 0x20000000
  16. #define SZ_1G 0x40000000
  17. static struct rt_memblock *mmblk_memory;
  18. static struct rt_memblock *mmblk_reserved;
  19. void rt_memblock_next_free_region_init(void);
  20. void rt_memblock_next_free_region(mmblk_flag_t flags, rt_size_t *out_start, rt_size_t *out_end);
  21. rt_bool_t rt_memblock_is_last_free(void);
  22. void rt_memblock_merge(void);
  23. struct rt_mmblk_reg *_nth_reg(struct rt_memblock *memblock, rt_uint32_t n)
  24. {
  25. struct rt_mmblk_reg *ret = RT_NULL;
  26. rt_slist_for_each_entry(ret, &(memblock->reg_list), node)
  27. {
  28. if (--n == 0)
  29. return ret;
  30. }
  31. return ret;
  32. }
  33. rt_uint32_t _reg_cnt(struct rt_memblock *memblock)
  34. {
  35. rt_uint32_t ret = 0;
  36. struct rt_mmblk_reg *reg;
  37. rt_slist_for_each_entry(reg, &(memblock->reg_list), node)
  38. {
  39. ret++;
  40. }
  41. return ret;
  42. }
  43. void _reset_memblock(void)
  44. {
  45. struct rt_mmblk_reg *reg;
  46. rt_slist_for_each_entry(reg, &(mmblk_memory->reg_list), node)
  47. {
  48. reg->alloc = RT_FALSE;
  49. }
  50. rt_slist_for_each_entry(reg, &(mmblk_reserved->reg_list), node)
  51. {
  52. reg->alloc = RT_FALSE;
  53. }
  54. mmblk_memory->reg_list.next = RT_NULL;
  55. mmblk_reserved->reg_list.next = RT_NULL;
  56. }
  57. static void test_memblock_add_simple(void)
  58. {
  59. _reset_memblock();
  60. rt_size_t base1 = SZ_1G, size1 = SZ_256M;
  61. rt_size_t base2 = SZ_128M, size2 = SZ_128M;
  62. rt_err_t err;
  63. err = rt_memblock_add_memory("memory1", base1, base1 + size1, MEMBLOCK_NONE);
  64. uassert_int_equal(err, RT_EOK);
  65. uassert_int_equal(_reg_cnt(mmblk_memory), 1);
  66. uassert_int_equal(_nth_reg(mmblk_memory, 1)->memreg.start, base1);
  67. uassert_int_equal(_nth_reg(mmblk_memory, 1)->memreg.end, base1 + size1);
  68. uassert_int_equal(_nth_reg(mmblk_memory, 1)->flags, MEMBLOCK_NONE);
  69. err = rt_memblock_add_memory("memory2", base2, base2 + size2, MEMBLOCK_HOTPLUG);
  70. uassert_int_equal(err, RT_EOK);
  71. uassert_int_equal(_reg_cnt(mmblk_memory), 2);
  72. uassert_int_equal(_nth_reg(mmblk_memory, 1)->memreg.start, base2);
  73. uassert_int_equal(_nth_reg(mmblk_memory, 1)->memreg.end, base2 + size2);
  74. uassert_int_equal(_nth_reg(mmblk_memory, 1)->flags, MEMBLOCK_HOTPLUG);
  75. uassert_int_equal(_nth_reg(mmblk_memory, 2)->memreg.start, base1);
  76. uassert_int_equal(_nth_reg(mmblk_memory, 2)->memreg.end, base1 + size1);
  77. uassert_int_equal(_nth_reg(mmblk_memory, 2)->flags, MEMBLOCK_NONE);
  78. }
  79. static void test_memblock_add_adjacent_top(void)
  80. {
  81. _reset_memblock();
  82. rt_size_t base1 = SZ_128M, size1 = SZ_128M;
  83. rt_size_t base2 = SZ_256M, size2 = SZ_128M;
  84. rt_err_t err;
  85. err = rt_memblock_add_memory("memory1", base1, base1 + size1, MEMBLOCK_NONE);
  86. uassert_int_equal(err, RT_EOK);
  87. err = rt_memblock_add_memory("memory2", base2, base2 + size2, MEMBLOCK_NONE);
  88. uassert_int_equal(err, RT_EOK);
  89. uassert_int_equal(_reg_cnt(mmblk_memory), 2);
  90. uassert_int_equal(_nth_reg(mmblk_memory, 1)->memreg.start, base1);
  91. uassert_int_equal(_nth_reg(mmblk_memory, 1)->memreg.end, base1 + size1);
  92. uassert_int_equal(_nth_reg(mmblk_memory, 1)->flags, MEMBLOCK_NONE);
  93. uassert_int_equal(_nth_reg(mmblk_memory, 2)->memreg.start, base2);
  94. uassert_int_equal(_nth_reg(mmblk_memory, 2)->memreg.end, base2 + size2);
  95. uassert_int_equal(_nth_reg(mmblk_memory, 2)->flags, MEMBLOCK_NONE);
  96. }
  97. static void test_memblock_add_adjacent_bottom(void)
  98. {
  99. _reset_memblock();
  100. rt_size_t base1 = SZ_256M, size1 = SZ_128M;
  101. rt_size_t base2 = SZ_128M, size2 = SZ_128M;
  102. rt_err_t err;
  103. err = rt_memblock_add_memory("memory1", base1, base1 + size1, MEMBLOCK_NONE);
  104. uassert_int_equal(err, RT_EOK);
  105. err = rt_memblock_add_memory("memory2", base2, base2 + size2, MEMBLOCK_NONE);
  106. uassert_int_equal(err, RT_EOK);
  107. uassert_int_equal(_reg_cnt(mmblk_memory), 2);
  108. uassert_int_equal(_nth_reg(mmblk_memory, 1)->memreg.start, base2);
  109. uassert_int_equal(_nth_reg(mmblk_memory, 1)->memreg.end, base2 + size2);
  110. uassert_int_equal(_nth_reg(mmblk_memory, 1)->flags, MEMBLOCK_NONE);
  111. uassert_int_equal(_nth_reg(mmblk_memory, 2)->memreg.start, base1);
  112. uassert_int_equal(_nth_reg(mmblk_memory, 2)->memreg.end, base1 + size1);
  113. uassert_int_equal(_nth_reg(mmblk_memory, 2)->flags, MEMBLOCK_NONE);
  114. }
  115. static void test_memblock_add_between(void)
  116. {
  117. _reset_memblock();
  118. rt_size_t base1 = SZ_512M, size1 = SZ_256M;
  119. rt_size_t base2 = SZ_1G, size2 = SZ_512M;
  120. rt_size_t base3 = SZ_512M + SZ_256M, size3 = SZ_256M;
  121. rt_err_t err;
  122. err = rt_memblock_add_memory("memory1", base1, base1 + size1, MEMBLOCK_NONE);
  123. uassert_int_equal(err, RT_EOK);
  124. err = rt_memblock_add_memory("memory2", base2, base2 + size2, MEMBLOCK_NONE);
  125. uassert_int_equal(err, RT_EOK);
  126. err = rt_memblock_add_memory("memory3", base3, base3 + size3, MEMBLOCK_HOTPLUG);
  127. uassert_int_equal(err, RT_EOK);
  128. uassert_int_equal(_reg_cnt(mmblk_memory), 3);
  129. uassert_int_equal(_nth_reg(mmblk_memory, 1)->memreg.start, base1);
  130. uassert_int_equal(_nth_reg(mmblk_memory, 1)->memreg.end, base1 + size1);
  131. uassert_int_equal(_nth_reg(mmblk_memory, 1)->flags, MEMBLOCK_NONE);
  132. uassert_int_equal(_nth_reg(mmblk_memory, 2)->memreg.start, base3);
  133. uassert_int_equal(_nth_reg(mmblk_memory, 2)->memreg.end, base3 + size3);
  134. uassert_int_equal(_nth_reg(mmblk_memory, 2)->flags, MEMBLOCK_HOTPLUG);
  135. uassert_int_equal(_nth_reg(mmblk_memory, 3)->memreg.start, base2);
  136. uassert_int_equal(_nth_reg(mmblk_memory, 3)->memreg.end, base2 + size2);
  137. uassert_int_equal(_nth_reg(mmblk_memory, 3)->flags, MEMBLOCK_NONE);
  138. }
  139. static void test_memblock_merge(void)
  140. {
  141. _reset_memblock();
  142. rt_size_t base1 = 0, size1 = SZ_256M;
  143. rt_size_t base2 = SZ_256M, size2 = SZ_256M;
  144. rt_size_t base3 = SZ_512M, size3 = SZ_256M;
  145. rt_size_t base4 = SZ_512M + SZ_256M, size4 = SZ_256M;
  146. rt_size_t base5 = SZ_1G, size5 = SZ_512M;
  147. rt_err_t err;
  148. err = rt_memblock_add_memory("memory1", base1, base1 + size1, MEMBLOCK_NONE);
  149. uassert_int_equal(err, RT_EOK);
  150. err = rt_memblock_add_memory("memory2", base2, base2 + size2, MEMBLOCK_NONE);
  151. uassert_int_equal(err, RT_EOK);
  152. err = rt_memblock_add_memory("memory3", base3, base3 + size3, MEMBLOCK_HOTPLUG);
  153. uassert_int_equal(err, RT_EOK);
  154. err = rt_memblock_add_memory("memory4", base4, base4 + size4, MEMBLOCK_NONE);
  155. uassert_int_equal(err, RT_EOK);
  156. err = rt_memblock_add_memory("memory5", base5, base5 + size5, MEMBLOCK_NONE);
  157. uassert_int_equal(err, RT_EOK);
  158. rt_memblock_merge();
  159. uassert_int_equal(_reg_cnt(mmblk_memory), 3);
  160. uassert_int_equal(_nth_reg(mmblk_memory, 1)->memreg.start, base1);
  161. uassert_int_equal(_nth_reg(mmblk_memory, 1)->memreg.end, base2 + size2);
  162. uassert_int_equal(_nth_reg(mmblk_memory, 1)->flags, MEMBLOCK_NONE);
  163. uassert_int_equal(_nth_reg(mmblk_memory, 2)->memreg.start, base3);
  164. uassert_int_equal(_nth_reg(mmblk_memory, 2)->memreg.end, base3 + size3);
  165. uassert_int_equal(_nth_reg(mmblk_memory, 2)->flags, MEMBLOCK_HOTPLUG);
  166. uassert_int_equal(_nth_reg(mmblk_memory, 3)->memreg.start, base4);
  167. uassert_int_equal(_nth_reg(mmblk_memory, 3)->memreg.end, base5 + size5);
  168. uassert_int_equal(_nth_reg(mmblk_memory, 3)->flags, MEMBLOCK_NONE);
  169. }
  170. static void test_memblock_add(void)
  171. {
  172. test_memblock_add_simple();
  173. test_memblock_add_adjacent_top();
  174. test_memblock_add_adjacent_bottom();
  175. test_memblock_add_between();
  176. test_memblock_merge();
  177. }
  178. static void test_memblock_reserve_in_memory_start(void)
  179. {
  180. _reset_memblock();
  181. rt_size_t base1 = SZ_128M, size1 = SZ_256M;
  182. rt_size_t baser = SZ_128M, sizer = SZ_128M;
  183. rt_size_t free_start, free_end;
  184. rt_err_t err;
  185. err = rt_memblock_add_memory("memory", base1, base1 + size1, MEMBLOCK_NONE);
  186. uassert_int_equal(err, RT_EOK);
  187. err = rt_memblock_reserve_memory("reserve", baser, baser + sizer, MEMBLOCK_NONE);
  188. uassert_int_equal(err, RT_EOK);
  189. rt_memblock_next_free_region_init();
  190. rt_memblock_next_free_region(MEMBLOCK_NONE, &free_start, &free_end);
  191. uassert_int_equal(free_start, SZ_256M);
  192. uassert_int_equal(free_end, SZ_128M + SZ_256M);
  193. rt_memblock_next_free_region(MEMBLOCK_NONE, &free_start, &free_end);
  194. uassert_int_equal(rt_memblock_is_last_free(), RT_TRUE);
  195. }
  196. static void test_memblock_reserve_in_memory_end(void)
  197. {
  198. _reset_memblock();
  199. rt_size_t base1 = SZ_128M, size1 = SZ_256M;
  200. rt_size_t baser = SZ_256M, sizer = SZ_128M;
  201. rt_size_t free_start, free_end;
  202. rt_err_t err;
  203. err = rt_memblock_add_memory("memory", base1, base1 + size1, MEMBLOCK_NONE);
  204. uassert_int_equal(err, RT_EOK);
  205. err = rt_memblock_reserve_memory("reserve", baser, baser + sizer, MEMBLOCK_NONE);
  206. uassert_int_equal(err, RT_EOK);
  207. rt_memblock_next_free_region_init();
  208. rt_memblock_next_free_region(MEMBLOCK_NONE, &free_start, &free_end);
  209. uassert_int_equal(free_start, SZ_128M);
  210. uassert_int_equal(free_end, SZ_256M);
  211. rt_memblock_next_free_region(MEMBLOCK_NONE, &free_start, &free_end);
  212. uassert_int_equal(rt_memblock_is_last_free(), RT_TRUE);
  213. }
  214. static void test_memblock_reserve_many_in_one_region(void)
  215. {
  216. _reset_memblock();
  217. rt_size_t base = 0, size = SZ_1G;
  218. rt_size_t baser1 = 0, sizer1 = SZ_128M;
  219. rt_size_t baser2 = SZ_256M, sizer2 = SZ_128M;
  220. rt_size_t baser3 = SZ_256M + SZ_128M, sizer3 = SZ_128M;
  221. rt_size_t baser4 = SZ_512M + SZ_128M, sizer4 = SZ_128M;
  222. rt_size_t baser5 = SZ_1G - SZ_128M, sizer5 = SZ_128M;
  223. rt_size_t free_start, free_end;
  224. rt_err_t err;
  225. err = rt_memblock_add_memory("memory", base, base + size, MEMBLOCK_NONE);
  226. uassert_int_equal(err, RT_EOK);
  227. err = rt_memblock_reserve_memory("reserve1", baser1, baser1 + sizer1, MEMBLOCK_NONE);
  228. uassert_int_equal(err, RT_EOK);
  229. err = rt_memblock_reserve_memory("reserve2", baser2, baser2 + sizer2, MEMBLOCK_NOMAP);
  230. uassert_int_equal(err, RT_EOK);
  231. err = rt_memblock_reserve_memory("reserve3", baser3, baser3 + sizer3, MEMBLOCK_NONE);
  232. uassert_int_equal(err, RT_EOK);
  233. err = rt_memblock_reserve_memory("reserve4", baser4, baser4 + sizer4, MEMBLOCK_NOMAP);
  234. uassert_int_equal(err, RT_EOK);
  235. err = rt_memblock_reserve_memory("reserve5", baser5, baser5 + sizer5, MEMBLOCK_NONE);
  236. uassert_int_equal(err, RT_EOK);
  237. rt_memblock_next_free_region_init();
  238. rt_memblock_next_free_region(MEMBLOCK_NONE, &free_start, &free_end);
  239. uassert_int_equal(free_start, SZ_128M);
  240. uassert_int_equal(free_end, SZ_256M);
  241. rt_memblock_next_free_region(MEMBLOCK_NONE, &free_start, &free_end);
  242. uassert_int_equal(free_start, SZ_512M);
  243. uassert_int_equal(free_end, SZ_512M + SZ_128M);
  244. rt_memblock_next_free_region(MEMBLOCK_NONE, &free_start, &free_end);
  245. uassert_int_equal(free_start, SZ_512M + SZ_256M);
  246. uassert_int_equal(free_end, SZ_1G - SZ_128M);
  247. rt_memblock_next_free_region(MEMBLOCK_NONE, &free_start, &free_end);
  248. uassert_int_equal(rt_memblock_is_last_free(), RT_TRUE);
  249. }
  250. static void test_memblock_reserve_large_region(void)
  251. {
  252. _reset_memblock();
  253. rt_size_t base1 = 0, size1 = SZ_256M;
  254. rt_size_t base2 = SZ_256M, size2 = SZ_256M;
  255. rt_size_t base3 = SZ_512M, size3 = SZ_256M;
  256. rt_size_t base4 = SZ_512M + SZ_256M, size4 = SZ_256M;
  257. rt_size_t baser = SZ_256M + SZ_128M, sizer = SZ_512M;
  258. rt_size_t free_start, free_end;
  259. rt_err_t err;
  260. err = rt_memblock_add_memory("memory1", base1, base1 + size1, MEMBLOCK_NONE);
  261. uassert_int_equal(err, RT_EOK);
  262. err = rt_memblock_add_memory("memory2", base2, base2 + size2, MEMBLOCK_NONE);
  263. uassert_int_equal(err, RT_EOK);
  264. err = rt_memblock_add_memory("memory3", base3, base3 + size3, MEMBLOCK_NONE);
  265. uassert_int_equal(err, RT_EOK);
  266. err = rt_memblock_add_memory("memory4", base4, base4 + size4, MEMBLOCK_NONE);
  267. uassert_int_equal(err, RT_EOK);
  268. err = rt_memblock_reserve_memory("reserve", baser, baser + sizer, MEMBLOCK_NOMAP);
  269. uassert_int_equal(err, RT_EOK);
  270. rt_memblock_next_free_region_init();
  271. rt_memblock_next_free_region(MEMBLOCK_NONE, &free_start, &free_end);
  272. uassert_int_equal(free_start, 0);
  273. uassert_int_equal(free_end, SZ_256M);
  274. rt_memblock_next_free_region(MEMBLOCK_NONE, &free_start, &free_end);
  275. uassert_int_equal(free_start, SZ_256M);
  276. uassert_int_equal(free_end, SZ_256M + SZ_128M);
  277. rt_memblock_next_free_region(MEMBLOCK_NONE, &free_start, &free_end);
  278. uassert_int_equal(free_start, SZ_512M + SZ_256M + SZ_128M);
  279. uassert_int_equal(free_end, SZ_1G);
  280. rt_memblock_next_free_region(MEMBLOCK_NONE, &free_start, &free_end);
  281. uassert_int_equal(rt_memblock_is_last_free(), RT_TRUE);
  282. }
  283. static void test_memblock_reserve(void)
  284. {
  285. test_memblock_reserve_in_memory_start();
  286. test_memblock_reserve_in_memory_end();
  287. test_memblock_reserve_many_in_one_region();
  288. test_memblock_reserve_large_region();
  289. }
  290. static rt_err_t utest_tc_init(void)
  291. {
  292. mmblk_memory = rt_memblock_get_memory();
  293. mmblk_reserved = rt_memblock_get_reserved();
  294. return RT_EOK;
  295. }
  296. static rt_err_t utest_tc_cleanup(void)
  297. {
  298. return RT_EOK;
  299. }
  300. static void testcase(void)
  301. {
  302. UTEST_UNIT_RUN(test_memblock_add);
  303. UTEST_UNIT_RUN(test_memblock_reserve);
  304. }
  305. UTEST_TC_EXPORT(testcase, "testcases.mm.memblock_tc", utest_tc_init, utest_tc_cleanup, 20);