rt_tlsf.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  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. static void (*rt_malloc_hook)(void *ptr, rt_size_t size);
  23. static void (*rt_free_hook)(void *ptr);
  24. void rt_malloc_sethook(void (*hook)(void *ptr, rt_size_t size))
  25. {
  26. rt_malloc_hook = hook;
  27. }
  28. void rt_free_sethook(void (*hook)(void *ptr))
  29. {
  30. rt_free_hook = hook;
  31. }
  32. #endif
  33. void rt_system_heap_init(void *begin_addr, void *end_addr)
  34. {
  35. size_t size;
  36. if (begin_addr < end_addr)
  37. {
  38. size = (rt_uint32_t)end_addr - (rt_uint32_t)begin_addr;
  39. }
  40. else
  41. {
  42. return;
  43. }
  44. if (!tlsf_ptr)
  45. {
  46. tlsf_ptr = (tlsf_t)tlsf_create_with_pool(begin_addr, size);
  47. rt_sem_init(&heap_sem, "heap", 1, RT_IPC_FLAG_PRIO);
  48. pools_list = rt_malloc(sizeof(struct pool_list));
  49. rt_slist_init(&pools_list->list);
  50. pools_list->pool_addr = tlsf_get_pool(tlsf_ptr);
  51. }
  52. else
  53. {
  54. RT_ASSERT(0);
  55. }
  56. }
  57. void *rt_system_heap_add(void *begin_addr, void *end_addr)
  58. {
  59. pool_t tlsf_pool;
  60. size_t size;
  61. pool_list_t heap;
  62. if (begin_addr < end_addr)
  63. {
  64. size = (rt_uint32_t)end_addr - (rt_uint32_t)begin_addr;
  65. }
  66. else
  67. {
  68. RT_ASSERT(0);
  69. }
  70. if (tlsf_ptr)
  71. {
  72. tlsf_pool = tlsf_add_pool(tlsf_ptr, begin_addr, size);
  73. if (tlsf_pool != RT_NULL)
  74. {
  75. heap = rt_malloc(sizeof(struct pool_list));
  76. rt_slist_append(&pools_list->list, &heap->list);
  77. heap->pool_addr = tlsf_pool;
  78. return heap;
  79. }
  80. }
  81. return RT_NULL;
  82. }
  83. void rt_system_heap_remove(void *heap)
  84. {
  85. RT_ASSERT(heap != RT_NULL);
  86. pool_list_t pool_node = (pool_list_t)heap;
  87. pool_t pool = pool_node->pool_addr;
  88. if (tlsf_ptr)
  89. {
  90. rt_slist_remove(&pools_list->list, &pool_node->list);
  91. rt_free(pool_node);
  92. tlsf_remove_pool(tlsf_ptr, pool);
  93. }
  94. }
  95. #ifdef PKG_TLSF_USING_ALIGN
  96. void *rt_malloc_align(rt_size_t size, rt_size_t align)
  97. {
  98. void *ptr = RT_NULL;
  99. if (tlsf_ptr)
  100. {
  101. rt_sem_take(&heap_sem, RT_WAITING_FOREVER);
  102. ptr = tlsf_memalign(tlsf_ptr, align, size);
  103. rt_sem_release(&heap_sem);
  104. }
  105. return ptr;
  106. }
  107. void rt_free_align(void *ptr)
  108. {
  109. rt_free(ptr);
  110. }
  111. #endif
  112. void *rt_malloc(rt_size_t nbytes)
  113. {
  114. void *ptr = RT_NULL;
  115. if (tlsf_ptr)
  116. {
  117. rt_sem_take(&heap_sem, RT_WAITING_FOREVER);
  118. ptr = tlsf_malloc(tlsf_ptr, nbytes);
  119. RT_OBJECT_HOOK_CALL(rt_malloc_hook, ((void *)ptr, nbytes));
  120. rt_sem_release(&heap_sem);
  121. }
  122. return ptr;
  123. }
  124. RTM_EXPORT(rt_malloc);
  125. void rt_free(void *ptr)
  126. {
  127. if (tlsf_ptr)
  128. {
  129. rt_sem_take(&heap_sem, RT_WAITING_FOREVER);
  130. tlsf_free(tlsf_ptr, ptr);
  131. RT_OBJECT_HOOK_CALL(rt_free_hook, (ptr));
  132. rt_sem_release(&heap_sem);
  133. }
  134. }
  135. RTM_EXPORT(rt_free);
  136. void *rt_realloc(void *ptr, rt_size_t nbytes)
  137. {
  138. if (tlsf_ptr)
  139. {
  140. rt_sem_take(&heap_sem, RT_WAITING_FOREVER);
  141. ptr = tlsf_realloc(tlsf_ptr, ptr, nbytes);
  142. rt_sem_release(&heap_sem);
  143. }
  144. return ptr;
  145. }
  146. RTM_EXPORT(rt_realloc);
  147. void *rt_calloc(rt_size_t count, rt_size_t size)
  148. {
  149. void *ptr = RT_NULL;
  150. rt_size_t total_size;
  151. total_size = count * size;
  152. ptr = rt_malloc(total_size);
  153. if (ptr != RT_NULL)
  154. {
  155. /* clean memory */
  156. rt_memset(ptr, 0, total_size);
  157. }
  158. return ptr;
  159. }
  160. RTM_EXPORT(rt_calloc);
  161. static size_t used_mem = 0;
  162. static size_t total_mem = 0;
  163. static void mem_info(void *ptr, size_t size, int used, void *user)
  164. {
  165. if (used)
  166. {
  167. used_mem += size;
  168. }
  169. total_mem += size;
  170. }
  171. void rt_memory_info(rt_uint32_t *total,
  172. rt_uint32_t *used,
  173. rt_uint32_t *max_used)
  174. {
  175. used_mem = 0;
  176. total_mem = 0;
  177. tlsf_walk_pool(tlsf_get_pool(tlsf_ptr), mem_info, 0);
  178. *total = total_mem;
  179. *used = used_mem;
  180. *max_used = used_mem;
  181. }
  182. void list_mem(void)
  183. {
  184. rt_uint8_t i = 0;
  185. rt_uint8_t len = 0;
  186. pool_list_t pool_node;
  187. struct rt_slist_node *node;
  188. node = &pools_list->list;
  189. used_mem = 0;
  190. total_mem = 0;
  191. len = rt_slist_len(node) + 1;
  192. for (i = 0; i < len; i++)
  193. {
  194. pool_node = rt_container_of(node, struct pool_list, list);
  195. tlsf_walk_pool(pool_node->pool_addr, mem_info, 0);
  196. node = node->next;
  197. }
  198. rt_kprintf("total memory: %d\n", total_mem);
  199. rt_kprintf("used memory : %d\n", used_mem);
  200. }
  201. #endif