1 /*
2 * Copyright (C) 2015-2018 Alibaba Group Holding Limited
3 */
4 #include "k_api.h"
5 #include "debug_api.h"
6
7 /* convert int to ascii(HEX)
8 while using format % in libc, malloc/free is involved.
9 this function avoid using malloc/free. so it works when heap corrupt. */
k_int2str(int num,char * str)10 char *k_int2str(int num, char *str)
11 {
12 char index[] = "0123456789ABCDEF";
13 unsigned int usnum = (unsigned int)num;
14
15 str[7] = index[usnum % 16];
16 usnum /= 16;
17 str[6] = index[usnum % 16];
18 usnum /= 16;
19 str[5] = index[usnum % 16];
20 usnum /= 16;
21 str[4] = index[usnum % 16];
22 usnum /= 16;
23 str[3] = index[usnum % 16];
24 usnum /= 16;
25 str[2] = index[usnum % 16];
26 usnum /= 16;
27 str[1] = index[usnum % 16];
28 usnum /= 16;
29 str[0] = index[usnum % 16];
30 usnum /= 16;
31
32 return str;
33 }
34
35 #if (K_MM_STATISTIC > 0)
debug_mm_overview(int (* print_func)(const char * fmt,...))36 void debug_mm_overview(int (*print_func)(const char *fmt, ...))
37 {
38 #if (RHINO_CONFIG_MM_BLK > 0)
39 mblk_info_t pool_info;
40 #endif
41
42 size_t max_free_blk_size = 0;
43 #if (RHINO_CONFIG_MM_TLF > 0)
44 max_free_blk_size = krhino_mm_max_free_size_get();
45 #endif
46
47 char s_heap_overview[] =
48 " | 0x | 0x | 0x | 0x | 0x |\r\n";
49
50 print_func(
51 "---------------------------------------------------------------------------\r\n");
52 print_func(
53 "[HEAP]| TotalSz | FreeSz | UsedSz | MinFreeSz | MaxFreeBlkSz |\r\n");
54
55 k_int2str((int)(g_kmm_head->free_size + g_kmm_head->used_size),
56 &s_heap_overview[10]);
57 k_int2str((int)g_kmm_head->free_size, &s_heap_overview[23]);
58 k_int2str((int)g_kmm_head->used_size, &s_heap_overview[36]);
59 k_int2str((int)(g_kmm_head->free_size + g_kmm_head->used_size -
60 g_kmm_head->maxused_size),
61 &s_heap_overview[49]);
62 k_int2str((int)max_free_blk_size, &s_heap_overview[62]);
63 print_func(s_heap_overview);
64
65 print_func(
66 "---------------------------------------------------------------------------\r\n");
67
68 #if (RHINO_CONFIG_MM_BLK > 0)
69 (void)krhino_mblk_info_nolock((mblk_pool_t *)g_kmm_head->fix_pool, &pool_info);
70 print_func(
71 "[POOL]| PoolSz | FreeSz | UsedSz | MinFreeSz | MaxFreeBlkSz |\r\n");
72
73 k_int2str((int)pool_info.pool_size, &s_heap_overview[10]);
74 k_int2str((int)(pool_info.pool_size - pool_info.used_size), &s_heap_overview[23]);
75 k_int2str((int)pool_info.used_size, &s_heap_overview[36]);
76 k_int2str((int)(pool_info.pool_size - pool_info.max_used_size), &s_heap_overview[49]);
77 k_int2str((int)pool_info.max_blk_size, &s_heap_overview[62]);
78 print_func(s_heap_overview);
79
80 print_func(
81 "---------------------------------------------------------------------------\r\n");
82 #endif
83 }
84 #else
debug_mm_overview(int (* print_func)(const char * fmt,...))85 void debug_mm_overview(int (*print_func)(const char *fmt, ...))
86 {
87 print_func("K_MM_STATISTIC in k_config.h is closed!\r\n");
88 }
89 #endif
90
91 #if (RHINO_CONFIG_KOBJ_LIST > 0)
debug_task_show(int (* print_func)(const char * fmt,...),ktask_t * task)92 static void debug_task_show(int (*print_func)(const char *fmt, ...), ktask_t *task)
93 {
94 size_t free_size;
95 int stat_idx;
96 int i;
97 int cpu_idx;
98 char *cpu_stat[] = { "UNK", "RDY", "PEND", "SUS",
99 "PEND_SUS", "SLP", "SLP_SUS", "DEL"
100 };
101 const name_t *task_name;
102
103 char s_task_overview[] = " 0x 0x "
104 " 0x (0x )\r\n";
105
106 if (krhino_task_stack_min_free(task, &free_size) != RHINO_SUCCESS) {
107 free_size = 0;
108 }
109 free_size *= sizeof(cpu_stack_t);
110
111 /* set name */
112 task_name = task->task_name == NULL ? "anonym" : task->task_name;
113 for (i = 0; i < 20; i++) {
114 s_task_overview[i] = ' ';
115 }
116 for (i = 0; i < strlen(task_name); i++) {
117 s_task_overview[i] = task_name[i];
118 }
119
120 /* set state */
121 stat_idx = task->task_state >= sizeof(cpu_stat) / sizeof(char *)
122 ? 0
123 : task->task_state;
124 for (i = 21; i < 29; i++) {
125 s_task_overview[i] = ' ';
126 }
127 for (i = 21; i < 29; i++) {
128 if (cpu_stat[stat_idx][i - 21] == '\0') {
129 break;
130 }
131 s_task_overview[i] = cpu_stat[stat_idx][i - 21];
132 }
133
134 /* set stack priority */
135 k_int2str(task->prio, &s_task_overview[32]);
136
137 /* set stack info */
138 k_int2str((int)task->task_stack_base, &s_task_overview[43]);
139 k_int2str((int)task->stack_size * sizeof(cpu_stack_t),
140 &s_task_overview[54]);
141 k_int2str((int)free_size, &s_task_overview[65]);
142 cpu_idx = 65 + 17;
143
144 (void)cpu_idx;
145 #if (RHINO_CONFIG_CPU_NUM > 1)
146 s_task_overview[cpu_idx] = (uint8_t)('0' + task->cpu_binded);
147 s_task_overview[cpu_idx + 10] = (uint8_t)('0' + task->cpu_num);
148 s_task_overview[cpu_idx + 20] = (uint8_t)('0' + task->cur_exc);
149 #endif
150
151 /* print */
152 if (print_func == NULL) {
153 print_func = printf;
154 }
155 print_func(s_task_overview);
156
157 }
debug_task_overview(int (* print_func)(const char * fmt,...))158 void debug_task_overview(int (*print_func)(const char *fmt, ...))
159 {
160 klist_t *listnode;
161 ktask_t *task;
162
163 print_func("---------------------------------------------------------------"
164 "-----------\r\n");
165 #if (RHINO_CONFIG_CPU_NUM > 1)
166 print_func("TaskName State Prio Stack StackSize "
167 "(MinFree) cpu_binded cpu_num cur_exc\r\n");
168 #else
169 print_func("TaskName State Prio Stack StackSize "
170 "(MinFree)\r\n");
171 #endif
172 print_func("---------------------------------------------------------------"
173 "-----------\r\n");
174
175 for (listnode = g_kobj_list.task_head.next;
176 listnode != &g_kobj_list.task_head; listnode = listnode->next) {
177 task = krhino_list_entry(listnode, ktask_t, task_stats_item);
178 debug_task_show(print_func, task);
179 }
180 }
181 #else
debug_task_overview(int (* print_func)(const char * fmt,...))182 void debug_task_overview(int (*print_func)(const char *fmt, ...))
183 {
184 print_func("RHINO_CONFIG_KOBJ_LIST in k_config.h is closed!\r\n");
185 }
186 #endif /* #if (RHINO_CONFIG_KOBJ_LIST > 0) */
187
188 #if (RHINO_CONFIG_BUF_QUEUE > 0)
189 #if (RHINO_CONFIG_KOBJ_LIST > 0)
debug_buf_queue_overview(int (* print_func)(const char * fmt,...))190 void debug_buf_queue_overview(int (*print_func)(const char *fmt, ...))
191 {
192 int i;
193 klist_t *listnode;
194 klist_t *blk_list_head;
195 ktask_t *task;
196 kbuf_queue_t *buf_queue;
197 const name_t *task_name;
198 char s_buf_queue_overview[] = "0x 0x 0x 0x "
199 "0x \r\n";
200
201 print_func(
202 "------------------------------------------------------------------\r\n");
203 print_func(
204 "BufQueAddr TotalSize PeakNum CurrNum MinFreeSz TaskWaiting\r\n");
205 print_func(
206 "------------------------------------------------------------------\r\n");
207 for (listnode = g_kobj_list.buf_queue_head.next;
208 listnode != &g_kobj_list.buf_queue_head; listnode = listnode->next) {
209
210 buf_queue = krhino_list_entry(listnode, kbuf_queue_t, buf_queue_item);
211 if (buf_queue->blk_obj.obj_type != RHINO_BUF_QUEUE_OBJ_TYPE) {
212 print_func("BufQueue Type error!\r\n");
213 break;
214 }
215
216 /* set buf_queue information */
217 k_int2str((int)buf_queue, &s_buf_queue_overview[2]);
218 k_int2str((int)(buf_queue->ringbuf.end - buf_queue->ringbuf.buf),
219 &s_buf_queue_overview[13]);
220 k_int2str((int)buf_queue->peak_num, &s_buf_queue_overview[24]);
221 k_int2str((int)buf_queue->cur_num, &s_buf_queue_overview[35]);
222 k_int2str((int)buf_queue->min_free_buf_size, &s_buf_queue_overview[46]);
223
224 /* set pending task name */
225 blk_list_head = &buf_queue->blk_obj.blk_list;
226 if (is_klist_empty(blk_list_head)) {
227 task_name = " ";
228 } else {
229 task = krhino_list_entry(blk_list_head->next, ktask_t, task_list);
230 task_name = task->task_name == NULL ? "anonym" : task->task_name;
231 }
232
233 for (i = 0; i < 20; i++) {
234 s_buf_queue_overview[55 + i] = ' ';
235 }
236 for (i = 0; i < 20; i++) {
237 if (task_name[i] == '\0') {
238 break;
239 }
240 s_buf_queue_overview[55 + i] = task_name[i];
241 }
242
243 /* print */
244 print_func(s_buf_queue_overview);
245 }
246 }
247 #else
debug_buf_queue_overview(int (* print_func)(const char * fmt,...))248 void debug_buf_queue_overview(int (*print_func)(const char *fmt, ...))
249 {
250 print_func("RHINO_CONFIG_KOBJ_LIST in k_config.h is closed!\r\n");
251 }
252 #endif
253 #endif
254
255 #if (RHINO_CONFIG_QUEUE > 0)
256 #if (RHINO_CONFIG_KOBJ_LIST > 0)
debug_queue_overview(int (* print_func)(const char * fmt,...))257 void debug_queue_overview(int (*print_func)(const char *fmt, ...))
258 {
259 int i;
260 klist_t *listnode;
261 klist_t *blk_list_head;
262 ktask_t *task;
263 kqueue_t *queue;
264 const name_t *task_name;
265 char s_queue_overview[] =
266 "0x 0x 0x 0x \r\n";
267
268 print_func("-------------------------------------------------------\r\n");
269 print_func("QueAddr TotalSize PeakNum CurrNum TaskWaiting\r\n");
270 print_func("-------------------------------------------------------\r\n");
271
272 for (listnode = g_kobj_list.queue_head.next;
273 listnode != &g_kobj_list.queue_head; listnode = listnode->next) {
274
275 queue = krhino_list_entry(listnode, kqueue_t, queue_item);
276 if (queue->blk_obj.obj_type != RHINO_QUEUE_OBJ_TYPE) {
277 print_func("Queue Type error!\r\n");
278 break;
279 }
280
281 /* set queue information */
282 k_int2str((int)queue->msg_q.queue_start, &s_queue_overview[2]);
283 k_int2str((int)queue->msg_q.size, &s_queue_overview[13]);
284 k_int2str((int)queue->msg_q.peak_num, &s_queue_overview[24]);
285 k_int2str((int)queue->msg_q.cur_num, &s_queue_overview[35]);
286
287 /* set pending task name */
288 blk_list_head = &queue->blk_obj.blk_list;
289 if (is_klist_empty(blk_list_head)) {
290 task_name = " ";
291 } else {
292 task = krhino_list_entry(blk_list_head->next, ktask_t, task_list);
293 task_name = task->task_name == NULL ? "anonym" : task->task_name;
294 }
295
296 for (i = 0; i < 20; i++) {
297 s_queue_overview[44 + i] = ' ';
298 }
299 for (i = 0; i < 20; i++) {
300 if (task_name[i] == '\0') {
301 break;
302 }
303 s_queue_overview[44 + i] = task_name[i];
304 }
305
306 /* print */
307 print_func(s_queue_overview);
308 }
309 }
310 #else
debug_queue_overview(int (* print_func)(const char * fmt,...))311 void debug_queue_overview(int (*print_func)(const char *fmt, ...))
312 {
313 print_func("RHINO_CONFIG_KOBJ_LIST in k_config.h is closed!\r\n");
314 }
315 #endif
316 #endif
317
318 #if (RHINO_CONFIG_SEM > 0)
319 #if (RHINO_CONFIG_KOBJ_LIST > 0)
debug_sem_overview(int (* print_func)(const char * fmt,...))320 void debug_sem_overview(int (*print_func)(const char *fmt, ...))
321 {
322 int i, cnt = 0;
323 ksem_t *sem;
324 ktask_t *task;
325 klist_t *listnode;
326 klist_t *blk_list_head;
327 const name_t *task_name;
328 char s_sem_overview[] =
329 "0x 0x 0x \r\n";
330 char s_sem_total[] =
331 "Total: 0x \r\n";
332
333 print_func("--------------------------------------------\r\n");
334 print_func("SemAddr Count PeakCount TaskWaiting\r\n");
335 print_func("--------------------------------------------\r\n");
336
337 for (listnode = g_kobj_list.sem_head.next;
338 listnode != &g_kobj_list.sem_head; listnode = listnode->next) {
339
340 cnt++;
341
342 sem = krhino_list_entry(listnode, ksem_t, sem_item);
343 if (sem->blk_obj.obj_type != RHINO_SEM_OBJ_TYPE) {
344 print_func("Sem Type error sem addr %p!\r\n", sem);
345 break;
346 }
347
348 /* only show sem waited by task */
349 blk_list_head = &sem->blk_obj.blk_list;
350 if (is_klist_empty(blk_list_head)) {
351 continue;
352 }
353
354 /* set sem information */
355 k_int2str((int)sem, &s_sem_overview[2]);
356 k_int2str((int)sem->count, &s_sem_overview[13]);
357 k_int2str((int)sem->peak_count, &s_sem_overview[24]);
358
359 /* set pending task name */
360 blk_list_head = &sem->blk_obj.blk_list;
361 if (is_klist_empty(blk_list_head)) {
362 task_name = " ";
363 } else {
364 task = krhino_list_entry(blk_list_head->next, ktask_t, task_list);
365 task_name = task->task_name == NULL ? "anonym" : task->task_name;
366 }
367
368 for (i = 0; i < 20; i++) {
369 s_sem_overview[33 + i] = ' ';
370 }
371 for (i = 0; (i < 20) && i < strlen(task_name); i++) {
372 s_sem_overview[33 + i] = task_name[i];
373 }
374
375 /* print */
376 print_func(s_sem_overview);
377 }
378 k_int2str(cnt, &s_sem_total[9]);
379 print_func(s_sem_total);
380 }
381 #else
debug_sem_overview(int (* print_func)(const char * fmt,...))382 void debug_sem_overview(int (*print_func)(const char *fmt, ...))
383 {
384 print_func("RHINO_CONFIG_KOBJ_LIST in k_config.h is closed!\r\n");
385 }
386 #endif
387 #endif /* RHINO_CONFIG_SEM */
388
389 #if (RHINO_CONFIG_KOBJ_LIST > 0)
debug_mutex_overview(int (* print_func)(const char * fmt,...))390 void debug_mutex_overview(int (*print_func)(const char *fmt, ...))
391 {
392 int i, cnt = 0;
393 kmutex_t *mutex;
394 ktask_t *task;
395 klist_t *listnode;
396 klist_t *blk_list_head;
397 const name_t *task_name;
398 char s_mutex_overview[] =
399 "0x 0x \r\n";
400 char s_mutex_total[] =
401 "Total: 0x \r\n";
402
403 print_func("--------------------------------------------\r\n");
404 print_func("MutexAddr TaskOwner NestCnt TaskWaiting\r\n");
405 print_func("--------------------------------------------\r\n");
406
407 for (listnode = g_kobj_list.mutex_head.next;
408 listnode != &g_kobj_list.mutex_head; listnode = listnode->next) {
409
410 cnt++;
411
412 mutex = krhino_list_entry(listnode, kmutex_t, mutex_item);
413 if (mutex->blk_obj.obj_type != RHINO_MUTEX_OBJ_TYPE) {
414 print_func("Mutex Type error!\r\n");
415 break;
416 }
417
418 /* only show mutex waited by task */
419 task = mutex->mutex_task;
420 if (task == NULL) {
421 continue;
422 }
423
424 /* set mutex information */
425 k_int2str((int)mutex, &s_mutex_overview[2]);
426 k_int2str((int)mutex->owner_nested, &s_mutex_overview[34]);
427
428 /* set owner task name */
429 task_name = task->task_name == NULL ? "anonym" : task->task_name;
430 for (i = 0; i < 20; i++) {
431 s_mutex_overview[11 + i] = ' ';
432 }
433 for (i = 0; i <= strlen(task_name); i++) {
434 s_mutex_overview[11 + i] = task_name[i];
435 }
436
437 /* set pending task name */
438 blk_list_head = &mutex->blk_obj.blk_list;
439 if (!is_klist_empty(blk_list_head)) {
440 task = krhino_list_entry(blk_list_head->next, ktask_t, task_list);
441 task_name = task->task_name == NULL ? "anonym" : task->task_name;
442 for (i = 0; i < 20; i++) {
443 s_mutex_overview[43 + i] = ' ';
444 }
445 for (i = 0; (i < 20) && (i < strlen(task_name)); i++) {
446 s_mutex_overview[43 + i] = task_name[i];
447 }
448 }
449
450 /* print */
451 print_func(s_mutex_overview);
452 }
453
454 k_int2str(cnt, &s_mutex_total[9]);
455 print_func(s_mutex_total);
456 }
457 #else
debug_mutex_overview(int (* print_func)(const char * fmt,...))458 void debug_mutex_overview(int (*print_func)(const char *fmt, ...))
459 {
460 print_func("RHINO_CONFIG_KOBJ_LIST in k_config.h is closed!\r\n");
461 }
462 #endif
463
debug_overview(int (* print_func)(const char * fmt,...))464 void debug_overview(int (*print_func)(const char *fmt, ...))
465 {
466 #if (RHINO_CONFIG_MM_TLF > 0)
467 print_func("========== Heap Info ==========\r\n");
468 debug_mm_overview(print_func);
469 #endif
470 print_func("========== Task Info ==========\r\n");
471 debug_task_overview(print_func);
472 #if (RHINO_CONFIG_QUEUE > 0)
473 print_func("========== Queue Info ==========\r\n");
474 debug_queue_overview(print_func);
475 #endif
476 #if (RHINO_CONFIG_BUF_QUEUE > 0)
477 print_func("======== Buf Queue Info ========\r\n");
478 debug_buf_queue_overview(print_func);
479 #endif
480 #if (RHINO_CONFIG_SEM > 0)
481 print_func("========== Sem Waiting ==========\r\n");
482 debug_sem_overview(print_func);
483 #endif
484 print_func("========= Mutex Waiting =========\r\n");
485 debug_mutex_overview(print_func);
486 }
487
488 #if (K_MM_STATISTIC > 0)
489 #if (RHINO_CONFIG_MM_TLF > 0)
debug_heap_info_get(debug_mm_info_t * mm_info)490 void debug_heap_info_get(debug_mm_info_t *mm_info)
491 {
492 mm_info->total_size = g_kmm_head->free_size + g_kmm_head->used_size;
493 mm_info->free_size = g_kmm_head->free_size;
494 mm_info->used_size = g_kmm_head->used_size;
495 mm_info->maxused_size = g_kmm_head->maxused_size;
496 mm_info->maxblk_size = -1; /* not support current, will be replaced by krhino_mm_max_free_size_get() */
497 return;
498 }
499 #endif
500
501 #if (RHINO_CONFIG_MM_BLK > 0)
debug_pool_info_get(debug_mm_info_t * mm_info)502 void debug_pool_info_get(debug_mm_info_t *mm_info)
503 {
504 mblk_info_t pool_info;
505 (void)krhino_mblk_info_nolock((mblk_pool_t *)g_kmm_head->fix_pool, &pool_info);
506 mm_info->total_size = pool_info.pool_size;
507 mm_info->free_size = pool_info.pool_size - pool_info.used_size;
508 mm_info->used_size = pool_info.used_size;
509 mm_info->maxused_size = pool_info.max_used_size;
510 mm_info->maxblk_size = pool_info.max_blk_size;
511 return;
512 }
513 #endif
514 #endif
515
516