1 /*
2 * Copyright (C) 2015-2017 Alibaba Group Holding Limited
3 */
4
5 #include <stdio.h>
6 #include "k_api.h"
7
8 #if AOS_COMP_DEBUG
9 #include "aos/debug.h"
10 #endif
11
12 #if 0
13 #include "cli_console.h"
14
15 extern cli_console cli_uart_console;
16 #define KMM_CRITICAL_ENTER(head, cpsr) \
17 do { \
18 cli_console *console = get_current_console(); \
19 if(console && console == &cli_uart_console) { \
20 MM_CRITICAL_ENTER(head, cpsr); \
21 } \
22 } while(0);
23
24 #define KMM_CRITICAL_EXIT(head, cpsr) \
25 do { \
26 cli_console *console = get_current_console(); \
27 if(console && console == &cli_uart_console) { \
28 MM_CRITICAL_EXIT(head, cpsr); \
29 } \
30 } while(0);
31
32 #endif
33 #define KMM_CRITICAL_ENTER(head, cpsr) MM_CRITICAL_ENTER(head, cpsr)
34 #define KMM_CRITICAL_EXIT(head, cpsr) MM_CRITICAL_EXIT(head, cpsr)
35
36 typedef int (*KMM_PRINT)(const char *fmt, ...);
37
38 KMM_PRINT print = printf;
39
40 #if (RHINO_CONFIG_MM_DEBUG > 0)
41 uint8_t g_mmlk_cnt;
42
43 #define MM_CHK 0xff
44
45 #if (RHINO_CONFIG_MM_TLF > 0)
46
print_block(k_mm_list_t * b)47 void print_block(k_mm_list_t *b)
48 {
49 if (!b) {
50 return;
51 }
52
53 print("0x%p ", (void *)b);
54
55 if (b->buf_size & MM_BUFF_FREE) {
56 if (b->dye != MM_DYE_FREE) {
57 print("!");
58 } else {
59 print(" ");
60 }
61 print("free ");
62 } else {
63 if (b->dye != MM_DYE_USED) {
64 print("!");
65 } else {
66 print(" ");
67 }
68 print("used ");
69 }
70
71 if (MM_GET_BUF_SIZE(b)) {
72 print(" %6lu ", (unsigned long)MM_GET_BUF_SIZE(b));
73 } else {
74 print(" sentinel ");
75 }
76
77 if (b->buf_size & MM_BUFF_FREE) {
78 if (b->dye != MM_DYE_FREE) {
79 print(" %8x ", b->dye);
80 } else {
81 print(" OK ");
82 }
83 } else {
84 if (b->dye != MM_DYE_USED) {
85 print(" %8x ", b->dye);
86 } else {
87 print(" OK ");
88 }
89 }
90
91 print(" 0x%-8x ", b->owner);
92
93 #if (RHINO_CONFIG_MM_TRACE_LVL > 0)
94 /* If double free, print last alloc trace maybe useful.
95 This info is not useful if this mem alloc-and-freed by another module between.
96 */
97 //if ((b->buf_size & MM_BUFF_FREE) == 0)
98 {
99 int idx;
100 print(" (%p", b->trace[0]);
101 for (idx = 1 ; idx < RHINO_CONFIG_MM_TRACE_LVL ; idx++) {
102 print(" <- %p", b->trace[idx]);
103 }
104 print(")");
105 }
106 #endif
107
108 print("\r\n");
109 }
110
check_block(k_mm_list_t * b)111 void check_block(k_mm_list_t *b)
112 {
113 if (!b) {
114 return;
115 }
116
117 if (b->buf_size & MM_BUFF_FREE) {
118 if (b->dye != MM_DYE_FREE) {
119 print("0x%p ", (void *)b);
120 }
121 } else {
122 if (b->dye != MM_DYE_USED) {
123 print("0x%p ", (void *)b);
124 }
125 }
126 }
127
128
dump_kmm_free_map(k_mm_head * mmhead)129 void dump_kmm_free_map(k_mm_head *mmhead)
130 {
131 int i;
132
133 k_mm_list_t *next;
134 k_mm_list_t *tmp;
135
136 if (!mmhead) {
137 return;
138 }
139
140 print("freelist bitmap: 0x%x\r\n", (unsigned)mmhead->free_bitmap);
141 print(" Address Stat Len Chk Caller\r\n");
142
143 for (i = 0; i < MM_BIT_LEVEL; i++) {
144 next = mmhead->freelist[i];
145 while (next) {
146 print_block(next);
147 tmp = next->mbinfo.free_ptr.next;
148 next = tmp;
149 }
150 }
151 }
152
dump_kmm_map(k_mm_head * mmhead)153 void dump_kmm_map(k_mm_head *mmhead)
154 {
155 k_mm_region_info_t *reginfo, *nextreg;
156 k_mm_list_t *next, *cur;
157
158 if (!mmhead) {
159 return;
160 }
161
162 print("ALL BLOCKS\r\n");
163 print("Blk_Addr Stat Len Chk Caller Point\r\n");
164 reginfo = mmhead->regioninfo;
165 while (reginfo) {
166 cur = MM_GET_THIS_BLK(reginfo);
167 while (cur) {
168 print_block(cur);
169 if (MM_GET_BUF_SIZE(cur)) {
170 next = MM_GET_NEXT_BLK(cur);
171 } else {
172 next = NULL;
173 }
174 cur = next;
175 }
176 nextreg = reginfo->next;
177 reginfo = nextreg;
178 }
179 }
180
dump_kmm_statistic_info(k_mm_head * mmhead)181 void dump_kmm_statistic_info(k_mm_head *mmhead)
182 {
183 #if (K_MM_STATISTIC > 0)
184 int i;
185 #endif
186
187 if (!mmhead) {
188 return;
189 }
190
191 #if (K_MM_STATISTIC > 0)
192 for (i = 0; i < MM_BIT_LEVEL; i++) {
193 if (i % 4 == 0 && i != 0) {
194 print("\r\n");
195 }
196 print("[2^%02d] bytes: %5d |", (i + MM_MIN_BIT), mmhead->alloc_times[i]);
197 }
198 print("\r\n");
199 #endif
200 }
201
202 #if (RHINO_CONFIG_MM_BLK > 0)
dump_kmm_mblk_info(k_mm_head * mmhead)203 void dump_kmm_mblk_info(k_mm_head *mmhead)
204 {
205 uint32_t idx;
206 uint32_t slice = 0;
207 mblk_list_t *blk_list;
208 mblk_pool_t *mm_pool;
209
210 size_t UsedSize = 0;
211 size_t FreeSize = 0;
212 size_t MaxUsedSz = 0;
213 size_t AllocFail = 0;
214
215 print(
216 "---------------------------------------------------------------------------\r\n");
217 print(
218 "[POOL]| BlkSize | UsedSize | FreeSize | MaxUsedSz | AllocFail |\r\n");
219
220 mm_pool = mmhead->fix_pool;
221 if (mm_pool != NULL) {
222 for (idx = 0 ; idx < MM_BLK_SLICE_BIT ; idx++) {
223 blk_list = &(mm_pool->blk_list[idx]);
224 if (blk_list->slice_cnt > 0) {
225 print(" | %-10d | %-10d | %-10d | %-10d | %-10d |\r\n",
226 blk_list->blk_size, \
227 (int)blk_list->nofree_cnt * blk_list->blk_size,
228 (int)blk_list->freelist_cnt * blk_list->blk_size,
229 (blk_list->slice_cnt - 1)*MM_BLK_SLICE_SIZE + blk_list->slice_offset,
230 (int)blk_list->fail_cnt);
231
232 UsedSize += blk_list->nofree_cnt * blk_list->blk_size;
233 FreeSize += blk_list->freelist_cnt * blk_list->blk_size;
234 MaxUsedSz += (blk_list->slice_cnt - 1) * MM_BLK_SLICE_SIZE + blk_list->slice_offset;
235 AllocFail += blk_list->fail_cnt;
236
237 slice += blk_list->slice_cnt;
238 }
239 }
240 print("Total | | %-10d | %-10d | %-10d | %-10d |\r\n",
241 UsedSize, FreeSize, MaxUsedSz, AllocFail);
242
243 print("Pool Size %d, Free Slice size %p.\r\n",
244 mm_pool->pool_end - mm_pool->pool_start,
245 (intptr_t)(mm_pool->pool_end - mm_pool->pool_start - mm_pool->slice_cnt * MM_BLK_SLICE_SIZE));
246 }
247 print(
248 "---------------------------------------------------------------------------\r\n");
249 }
250 #endif
251
252 #if (RHINO_CONFIG_KOBJ_LIST > 0)
dump_kmm_task_info(k_mm_head * mmhead)253 void dump_kmm_task_info(k_mm_head *mmhead)
254 {
255 k_mm_region_info_t *reginfo;
256 k_mm_list_t *next, *cur;
257 ktask_t *task_owner;
258 uint32_t isr_alloc_size = 0;
259 uint32_t unk_alloc_size = 0;
260 uint32_t buff_size;
261
262 klist_t *listnode;
263 ktask_t *task;
264
265 if (!mmhead) {
266 return;
267 }
268
269 reginfo = mmhead->regioninfo;
270 while (reginfo) {
271 cur = MM_GET_THIS_BLK(reginfo);
272 while (cur) {
273 buff_size = MM_GET_BUF_SIZE(cur);
274 if (cur->dye == MM_DYE_USED) {
275 if (cur->owner_id == 0) {
276 isr_alloc_size += buff_size;
277 } else if (cur->owner_id != MM_OWNER_ID_SELF) {
278 task_owner = debug_task_find_by_id(cur->owner_id);
279 if (task_owner != NULL) {
280 task_owner->task_alloc_size += buff_size;
281 } else {
282 unk_alloc_size += buff_size;
283 }
284 }
285 }
286
287 if (buff_size) {
288 next = MM_GET_NEXT_BLK(cur);
289 } else {
290 next = NULL;
291 }
292 cur = next;
293 }
294 reginfo = reginfo->next;
295 }
296
297 print("TaskName Prio StackSize HeapAllocSize\r\n");
298
299 /* Traversing all task */
300 for (listnode = g_kobj_list.task_head.next;
301 listnode != &g_kobj_list.task_head; listnode = listnode->next) {
302
303 task = krhino_list_entry(listnode, ktask_t, task_stats_item);
304
305 if (task->task_alloc_size != 0) {
306 print("%-24s %-5d %-10d %-10d\r\n",
307 task->task_name, task->prio, (int)task->stack_size, (int)task->task_alloc_size);
308 task->task_alloc_size = 0;
309 }
310 }
311 #if (RHINO_CONFIG_MM_BLK > 0)
312 isr_alloc_size -= (RHINO_CONFIG_MM_TLF_BLK_SIZE + MM_ALIGN_UP(sizeof(mblk_pool_t)));
313 #endif
314 print("Allocated in ISR %d, Allocated by deleted task %d\r\n", (int)isr_alloc_size, (int)unk_alloc_size);
315 }
316 #else
dump_kmm_task_info(k_mm_head * mmhead)317 void dump_kmm_task_info(k_mm_head *mmhead)
318 {
319 print("need config RHINO_CONFIG_KOBJ_LIST > 0\r\n");
320 }
321 #endif
322
dumpsys_mm_info_func(uint32_t mm_status)323 uint32_t dumpsys_mm_info_func(uint32_t mm_status)
324 {
325 cpu_cpsr_t flags_cpsr = 0;
326
327 if (mm_status != KMM_ERROR_LOCKED) {
328 KMM_CRITICAL_ENTER(g_kmm_head, flags_cpsr);
329 } else {
330 print = printk;
331 }
332
333 print("\r\n");
334 print("------------------------------- all memory blocks --------------------------------- \r\n");
335 print("g_kmm_head = %8x\r\n", (unsigned int)g_kmm_head);
336 dump_kmm_map(g_kmm_head);
337
338 print("\r\n");
339 print("----------------------------- all free memory blocks ------------------------------ \r\n");
340 dump_kmm_free_map(g_kmm_head);
341
342 print("\r\n");
343 print("--------------------------- memory allocation statistic --------------------------- \r\n");
344 dump_kmm_statistic_info(g_kmm_head);
345
346 print("\r\n");
347 print("-------------------------------[kernel] heap size overview -------------------------------- \r\n");
348 debug_mm_overview(print);
349
350 #if (RHINO_CONFIG_MM_BLK > 0)
351 print("\r\n");
352 print("--------------------------- mmblk allocation statistic ---------------------------- \r\n");
353 dump_kmm_mblk_info(g_kmm_head);
354 #endif
355
356 print("\r\n");
357 print("--------------------------- task allocation statistic ----------------------------- \r\n");
358 dump_kmm_task_info(g_kmm_head);
359
360 print("\r\n");
361 print("----------------------------------------------------------------------------------- \r\n");
362
363 if (mm_status != KMM_ERROR_LOCKED) {
364 KMM_CRITICAL_EXIT(g_kmm_head, flags_cpsr);
365 }
366
367 return RHINO_SUCCESS;
368 }
369
dumpsys_mm_overview_func(uint32_t len)370 uint32_t dumpsys_mm_overview_func(uint32_t len)
371 {
372 cpu_cpsr_t flags_cpsr = 0;
373
374 KMM_CRITICAL_ENTER(g_kmm_head, flags_cpsr);
375
376 print("\r\n");
377 print("-------------------------------[kernel] heap size overview -------------------------------- \r\n");
378 debug_mm_overview(print);
379
380 #if (RHINO_CONFIG_MM_BLK > 0)
381 print("\r\n");
382 print("--------------------------- mmblk allocation statistic ---------------------------- \r\n");
383 dump_kmm_mblk_info(g_kmm_head);
384 #endif
385
386 print("\r\n");
387 print("--------------------------- task allocation statistic ----------------------------- \r\n");
388 dump_kmm_task_info(g_kmm_head);
389
390 KMM_CRITICAL_EXIT(g_kmm_head, flags_cpsr);
391
392 print("\r\n");
393 print("----------------------------------------------------------------------------------- \r\n");
394
395 return RHINO_SUCCESS;
396 }
397
398
399
dump_kmm_chk(k_mm_head * mmhead,uint8_t care_cnt)400 void dump_kmm_chk(k_mm_head *mmhead, uint8_t care_cnt)
401 {
402 k_mm_region_info_t *reginfo, *nextreg;
403 k_mm_list_t *next, *cur;
404
405 if (!mmhead || care_cnt == 0) {
406 return;
407 }
408
409 reginfo = mmhead->regioninfo;
410 while (reginfo) {
411 cur = MM_GET_THIS_BLK(reginfo);
412 while (cur) {
413 if (cur->trace_id == care_cnt) {
414 print_block(cur);
415 } else if (care_cnt == MM_CHK) {
416 check_block(cur);
417 }
418 if (MM_GET_BUF_SIZE(cur)) {
419 next = MM_GET_NEXT_BLK(cur);
420 } else {
421 next = NULL;
422 }
423 cur = next;
424 }
425 nextreg = reginfo->next;
426 reginfo = nextreg;
427 }
428 }
429
dumpsys_mm_leakcheck(uint32_t call_cnt,int32_t query_index)430 uint32_t dumpsys_mm_leakcheck(uint32_t call_cnt, int32_t query_index)
431 {
432 cpu_cpsr_t flags_cpsr = 0;
433 KMM_CRITICAL_ENTER(g_kmm_head, flags_cpsr);
434
435 if (query_index < 0) {
436 query_index = g_mmlk_cnt;
437 g_mmlk_cnt = (uint8_t)call_cnt;
438 } else if (query_index > g_mmlk_cnt) {
439 printf("query_index should be less than %d\r\n", g_mmlk_cnt);
440 return -1;
441 }
442 print("-----------------All new alloced blocks:----------------\r\n");
443 print("Blk_Addr Stat Len Chk Caller Point\r\n");
444
445 dump_kmm_chk(g_kmm_head, query_index);
446
447 print("--------------New alloced blocks info ends.-------------\r\n");
448 print("\r\n");
449
450 KMM_CRITICAL_EXIT(g_kmm_head, flags_cpsr);
451 return RHINO_SUCCESS;
452 }
453
dumpsys_mm_header_check(void)454 void dumpsys_mm_header_check(void)
455 {
456 cpu_cpsr_t flags_cpsr = 0;
457 KMM_CRITICAL_ENTER(g_kmm_head, flags_cpsr);
458
459 print("-----------------All error blocks:----------------\r\n");
460
461 dump_kmm_chk(g_kmm_head, MM_CHK);
462 print("\r\n");
463
464 KMM_CRITICAL_EXIT(g_kmm_head, flags_cpsr);
465 }
466
467 #endif /* #if (RHINO_CONFIG_MM_TLF > 0) */
468
469 #endif /* #if (RHINO_CONFIG_MM_DEBUG > 0) */
470
471