heap_regions_debug.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. #include "heap_regions_debug.h"
  2. #include "FreeRTOS.h"
  3. #include "task.h"
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #if (configENABLE_MEMORY_DEBUG == 1)
  8. static os_block_t g_malloc_list, *g_free_list=NULL, *g_end;
  9. static size_t g_heap_struct_size;
  10. static mem_dbg_ctl_t g_mem_dbg;
  11. char g_mem_print = 0;
  12. static portMUX_TYPE *g_malloc_mutex = NULL;
  13. #define MEM_DEBUG(...)
  14. void mem_debug_init(size_t size, void *start, void *end, portMUX_TYPE *mutex)
  15. {
  16. MEM_DEBUG("size=%d start=%p end=%p mutex=%p%x\n", size, start, end, mutex);
  17. memset(&g_mem_dbg, 0, sizeof(g_mem_dbg));
  18. memset(&g_malloc_list, 0, sizeof(g_malloc_list));
  19. g_malloc_mutex = mutex;
  20. g_heap_struct_size = size;
  21. g_free_list = start;
  22. g_end = end;
  23. }
  24. void mem_debug_push(char type, void *addr)
  25. {
  26. os_block_t *b = (os_block_t*)addr;
  27. debug_block_t *debug_b = DEBUG_BLOCK(b);
  28. MEM_DEBUG("push type=%d addr=%p\n", type, addr);
  29. if (g_mem_print){
  30. if (type == DEBUG_TYPE_MALLOC){
  31. ets_printf("task=%s t=%s s=%u a=%p\n", debug_b->head.task?debug_b->head.task:"", type==DEBUG_TYPE_MALLOC?"m":"f", b->size, addr);
  32. } else {
  33. ets_printf("task=%s t=%s s=%u a=%p\n", debug_b->head.task?debug_b->head.task:"", type==DEBUG_TYPE_MALLOC?"m":"f", b->size, addr);
  34. }
  35. } else {
  36. mem_dbg_info_t *info = &g_mem_dbg.info[g_mem_dbg.cnt%DEBUG_MAX_INFO_NUM];
  37. info->addr = addr;
  38. info->type = type;
  39. info->time = g_mem_dbg.cnt;
  40. g_mem_dbg.cnt++;
  41. }
  42. }
  43. void mem_debug_malloc_show(void)
  44. {
  45. os_block_t *b = g_malloc_list.next;
  46. debug_block_t *d;
  47. taskENTER_CRITICAL(g_malloc_mutex);
  48. while (b){
  49. d = DEBUG_BLOCK(b);
  50. d->head.task[3] = '\0';
  51. ets_printf("t=%s s=%u a=%p\n", d->head.task?d->head.task:"", b->size, b);
  52. b = b->next;
  53. }
  54. taskEXIT_CRITICAL(g_malloc_mutex);
  55. }
  56. void mem_debug_show(void)
  57. {
  58. uint32_t i;
  59. if (!g_mem_print) return;
  60. for (i=0; i<DEBUG_MAX_INFO_NUM; i++){
  61. ets_printf("%u %s %p\n", g_mem_dbg.info[i].time, g_mem_dbg.info[i].type == DEBUG_TYPE_FREE?"f":"m", g_mem_dbg.info[i].addr);
  62. }
  63. }
  64. void mem_check_block(void* data)
  65. {
  66. debug_block_t *b = DEBUG_BLOCK(data);
  67. MEM_DEBUG("check block data=%p\n", data);
  68. if (data && (HEAD_DOG(b) == DEBUG_DOG_VALUE)){
  69. if (TAIL_DOG(b) != DEBUG_DOG_VALUE){
  70. ets_printf("f task=%s a=%p h=%08x t=%08x\n", b->head.task?b->head.task:"", b, HEAD_DOG(b), TAIL_DOG(b));
  71. DOG_ASSERT();
  72. }
  73. } else {
  74. ets_printf("f task=%s a=%p h=%08x\n", b->head.task?b->head.task:"", b, HEAD_DOG(b));\
  75. DOG_ASSERT();
  76. }
  77. }
  78. void mem_init_dog(void *data)
  79. {
  80. debug_block_t *b = DEBUG_BLOCK(data);
  81. xTaskHandle task;
  82. MEM_DEBUG("init dog, data=%p debug_block=%p block_size=%x\n", data, b, b->os_block.size);
  83. if (!data) return;
  84. #if (INCLUDE_pcTaskGetTaskName == 1)
  85. task = xTaskGetCurrentTaskHandle();
  86. if (task){
  87. strncpy(b->head.task, pcTaskGetTaskName(task), 3);
  88. b->head.task[3] = '\0';
  89. }
  90. #else
  91. b->head.task = '\0';
  92. #endif
  93. HEAD_DOG(b) = DEBUG_DOG_VALUE;
  94. TAIL_DOG(b) = DEBUG_DOG_VALUE;
  95. }
  96. void mem_check_all(void* pv)
  97. {
  98. os_block_t *b;
  99. if (pv){
  100. char *puc = (char*)(pv);
  101. os_block_t *b;
  102. puc -= (g_heap_struct_size - BLOCK_TAIL_LEN - BLOCK_HEAD_LEN);
  103. b = (os_block_t*)puc;
  104. mem_check_block(b);
  105. }
  106. taskENTER_CRITICAL(g_malloc_mutex);
  107. b = g_free_list->next;
  108. while(b && b != g_end){
  109. mem_check_block(b);
  110. ets_printf("check b=%p size=%d ok\n", b, b->size);
  111. b = b->next;
  112. }
  113. taskEXIT_CRITICAL(g_malloc_mutex);
  114. }
  115. void mem_malloc_show(void)
  116. {
  117. os_block_t *b = g_malloc_list.next;
  118. debug_block_t *debug_b;
  119. while (b){
  120. debug_b = DEBUG_BLOCK(b);
  121. ets_printf("%s %p %p %u\n", debug_b->head.task, debug_b, b, b->size);
  122. b = b->next;
  123. }
  124. }
  125. void mem_malloc_block(void *data)
  126. {
  127. os_block_t *b = (os_block_t*)data;
  128. MEM_DEBUG("mem malloc block data=%p, size=%u\n", data, b->size);
  129. mem_debug_push(DEBUG_TYPE_MALLOC, data);
  130. if (b){
  131. b->next = g_malloc_list.next;
  132. g_malloc_list.next = b;
  133. }
  134. }
  135. void mem_free_block(void *data)
  136. {
  137. os_block_t *del = (os_block_t*)data;
  138. os_block_t *b = g_malloc_list.next;
  139. os_block_t *pre = &g_malloc_list;
  140. debug_block_t *debug_b;
  141. MEM_DEBUG("mem free block data=%p, size=%d\n", data, del->size);
  142. mem_debug_push(DEBUG_TYPE_FREE, data);
  143. if (!del) {
  144. return;
  145. }
  146. while (b){
  147. if ( (del == b) ){
  148. pre->next = b->next;
  149. b->next = NULL;
  150. return;
  151. }
  152. pre = b;
  153. b = b->next;
  154. }
  155. debug_b = DEBUG_BLOCK(del);
  156. ets_printf("%s %p %p %u already free\n", debug_b->head.task, debug_b, del, del->size);
  157. mem_malloc_show();
  158. abort();
  159. }
  160. #endif