rt_tlsf.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. */
  9. #include <rtthread.h>
  10. #include "rt_tlsf.h"
  11. #if defined (RT_USING_USERHEAP) && defined (PKG_USING_TLSF)
  12. static tlsf_t tlsf_ptr = 0;
  13. static struct rt_semaphore heap_sem;
  14. struct pool_list
  15. {
  16. pool_t pool_addr;
  17. rt_slist_t list;
  18. };
  19. typedef struct pool_list *pool_list_t;
  20. static pool_list_t pools_list;
  21. #ifdef RT_USING_HOOK
  22. #if defined(RT_VERSION_CHECK) && (RTTHREAD_VERSION >= RT_VERSION_CHECK(5, 1, 0))
  23. static void (*rt_malloc_hook)(void **ptr, rt_size_t size);
  24. static void (*rt_free_hook)(void **ptr);
  25. void rt_malloc_sethook(void (*hook)(void **ptr, rt_size_t size))
  26. {
  27. rt_malloc_hook = hook;
  28. }
  29. void rt_free_sethook(void (*hook)(void **ptr))
  30. {
  31. rt_free_hook = hook;
  32. }
  33. #else
  34. static void (*rt_malloc_hook)(void *ptr, rt_size_t size);
  35. static void (*rt_free_hook)(void *ptr);
  36. void rt_malloc_sethook(void (*hook)(void *ptr, rt_size_t size))
  37. {
  38. rt_malloc_hook = hook;
  39. }
  40. void rt_free_sethook(void (*hook)(void *ptr))
  41. {
  42. rt_free_hook = hook;
  43. }
  44. #endif
  45. #endif
  46. rt_inline void tlsf_lock(void)
  47. {
  48. if (rt_thread_self())
  49. {
  50. rt_sem_take(&heap_sem, RT_WAITING_FOREVER);
  51. }
  52. }
  53. rt_inline void tlsf_unlock(void)
  54. {
  55. if (rt_thread_self())
  56. {
  57. rt_sem_release(&heap_sem);
  58. }
  59. }
  60. void rt_system_heap_init(void *begin_addr, void *end_addr)
  61. {
  62. size_t size;
  63. if (begin_addr < end_addr)
  64. {
  65. size = (rt_uint32_t)end_addr - (rt_uint32_t)begin_addr;
  66. }
  67. else
  68. {
  69. return;
  70. }
  71. if (!tlsf_ptr)
  72. {
  73. tlsf_ptr = (tlsf_t)tlsf_create_with_pool(begin_addr, size);
  74. rt_sem_init(&heap_sem, "heap", 1, RT_IPC_FLAG_PRIO);
  75. pools_list = rt_malloc(sizeof(struct pool_list));
  76. rt_slist_init(&pools_list->list);
  77. pools_list->pool_addr = tlsf_get_pool(tlsf_ptr);
  78. }
  79. else
  80. {
  81. RT_ASSERT(0);
  82. }
  83. }
  84. void *rt_system_heap_add(void *begin_addr, void *end_addr)
  85. {
  86. pool_t tlsf_pool;
  87. size_t size;
  88. pool_list_t heap;
  89. if (begin_addr < end_addr)
  90. {
  91. size = (rt_uint32_t)end_addr - (rt_uint32_t)begin_addr;
  92. }
  93. else
  94. {
  95. RT_ASSERT(0);
  96. }
  97. if (tlsf_ptr)
  98. {
  99. tlsf_pool = tlsf_add_pool(tlsf_ptr, begin_addr, size);
  100. if (tlsf_pool != RT_NULL)
  101. {
  102. heap = rt_malloc(sizeof(struct pool_list));
  103. rt_slist_append(&pools_list->list, &heap->list);
  104. heap->pool_addr = tlsf_pool;
  105. return heap;
  106. }
  107. }
  108. return RT_NULL;
  109. }
  110. void rt_system_heap_remove(void *heap)
  111. {
  112. RT_ASSERT(heap != RT_NULL);
  113. pool_list_t pool_node = (pool_list_t)heap;
  114. pool_t pool = pool_node->pool_addr;
  115. if (tlsf_ptr)
  116. {
  117. rt_slist_remove(&pools_list->list, &pool_node->list);
  118. rt_free(pool_node);
  119. tlsf_remove_pool(tlsf_ptr, pool);
  120. }
  121. }
  122. #ifdef PKG_TLSF_USING_ALIGN
  123. void *rt_malloc_align(rt_size_t size, rt_size_t align)
  124. {
  125. void *ptr = RT_NULL;
  126. if (tlsf_ptr)
  127. {
  128. tlsf_lock();
  129. ptr = tlsf_memalign(tlsf_ptr, align, size);
  130. tlsf_unlock();
  131. }
  132. return ptr;
  133. }
  134. void rt_free_align(void *ptr)
  135. {
  136. rt_free(ptr);
  137. }
  138. #endif
  139. void *rt_malloc(rt_size_t nbytes)
  140. {
  141. void *ptr = RT_NULL;
  142. if (tlsf_ptr)
  143. {
  144. tlsf_lock();
  145. ptr = tlsf_malloc(tlsf_ptr, nbytes);
  146. RT_OBJECT_HOOK_CALL(rt_malloc_hook, ((void *)ptr, nbytes));
  147. tlsf_unlock();
  148. }
  149. return ptr;
  150. }
  151. RTM_EXPORT(rt_malloc);
  152. void rt_free(void *ptr)
  153. {
  154. if (tlsf_ptr)
  155. {
  156. tlsf_lock();
  157. tlsf_free(tlsf_ptr, ptr);
  158. RT_OBJECT_HOOK_CALL(rt_free_hook, (ptr));
  159. tlsf_unlock();
  160. }
  161. }
  162. RTM_EXPORT(rt_free);
  163. void *rt_realloc(void *ptr, rt_size_t nbytes)
  164. {
  165. if (tlsf_ptr)
  166. {
  167. tlsf_lock();
  168. ptr = tlsf_realloc(tlsf_ptr, ptr, nbytes);
  169. tlsf_unlock();
  170. }
  171. return ptr;
  172. }
  173. RTM_EXPORT(rt_realloc);
  174. void *rt_calloc(rt_size_t count, rt_size_t size)
  175. {
  176. void *ptr = RT_NULL;
  177. rt_size_t total_size;
  178. total_size = count * size;
  179. ptr = rt_malloc(total_size);
  180. if (ptr != RT_NULL)
  181. {
  182. /* clean memory */
  183. rt_memset(ptr, 0, total_size);
  184. }
  185. return ptr;
  186. }
  187. RTM_EXPORT(rt_calloc);
  188. static size_t used_mem = 0;
  189. static size_t total_mem = 0;
  190. static void mem_info(void *ptr, size_t size, int used, void *user)
  191. {
  192. if (used)
  193. {
  194. used_mem += size;
  195. }
  196. total_mem += size;
  197. }
  198. void rt_memory_info(rt_size_t *total,
  199. rt_size_t *used,
  200. rt_size_t *max_used)
  201. {
  202. used_mem = 0;
  203. total_mem = 0;
  204. tlsf_walk_pool(tlsf_get_pool(tlsf_ptr), mem_info, 0);
  205. *total = total_mem;
  206. *used = used_mem;
  207. *max_used = used_mem;
  208. }
  209. void list_mem(void)
  210. {
  211. rt_uint8_t i = 0;
  212. rt_uint8_t len = 0;
  213. pool_list_t pool_node;
  214. struct rt_slist_node *node;
  215. node = &pools_list->list;
  216. used_mem = 0;
  217. total_mem = 0;
  218. len = rt_slist_len(node) + 1;
  219. for (i = 0; i < len; i++)
  220. {
  221. pool_node = rt_container_of(node, struct pool_list, list);
  222. tlsf_walk_pool(pool_node->pool_addr, mem_info, 0);
  223. node = node->next;
  224. }
  225. rt_kprintf("total memory: %d\n", total_mem);
  226. rt_kprintf("used memory : %d\n", used_mem);
  227. }
  228. static _tlsftrace_dump(void *ptr, size_t size, int used)
  229. {
  230. rt_kprintf("[0x%08x - ", ptr);
  231. if (size < 1024)
  232. {
  233. rt_kprintf("%5d", size);
  234. }
  235. else if (size < 1024 * 1024)
  236. {
  237. rt_kprintf("%4dK", size / 1024);
  238. }
  239. else
  240. {
  241. rt_kprintf("%4dM", size / (1024 * 1024));
  242. }
  243. if (used)
  244. {
  245. rt_kprintf("] used\n");
  246. }
  247. else
  248. {
  249. rt_kprintf("] free\n");
  250. }
  251. }
  252. int tlsftrace(void)
  253. {
  254. rt_kprintf("\n--memory item information --\n");
  255. tlsf_walk_pool(tlsf_get_pool(tlsf_ptr), _tlsftrace_dump, 0);
  256. return 0;
  257. }
  258. MSH_CMD_EXPORT(tlsftrace, dump tlsf memory trace information);
  259. #endif