mirror of
https://github.com/Ai-Thinker-Open/Ai-Thinker-Open_RTL8710BX_ALIOS_SDK.git
synced 2025-02-10 14:25:20 +00:00
468 lines
14 KiB
C
Executable file
468 lines
14 KiB
C
Executable file
/*
|
|
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <aos/aos.h>
|
|
|
|
#ifdef VCALL_RHINO
|
|
#include "k_api.h"
|
|
|
|
#define MM_LEAK_CHECK_ROUND_SCOND 10 * 1000
|
|
#define RHINO_BACKTRACE_DEPTH 10
|
|
|
|
extern char esc_tag[64];
|
|
|
|
#if (RHINO_CONFIG_MM_LEAKCHECK > 0)
|
|
extern uint32_t dump_mmleak(void);
|
|
#endif
|
|
|
|
ktimer_t g_mm_leak_check_timer;
|
|
|
|
#define safesprintf(buf, totallen, offset, string) \
|
|
do \
|
|
{ \
|
|
if ((totallen - offset) <= strlen(string)) \
|
|
{ \
|
|
csp_printf("%s", buf); \
|
|
offset = 0; \
|
|
} \
|
|
snprintf(buf + offset, strlen(string) + 1, "%s", string); \
|
|
offset += strlen(string); \
|
|
} while (0)
|
|
|
|
int dump_task_stack_byname(char *taskname);
|
|
|
|
uint32_t dumpsys_task_func(char *buf, uint32_t len, int detail)
|
|
{
|
|
kstat_t rst;
|
|
size_t free_size = 0;
|
|
sys_time_t time_total = 0;
|
|
/* consistent with "task_stat_t" */
|
|
char *cpu_stat[] = {"ERROR", "RDY", "PEND", "SUS",
|
|
"PEND_SUS", "SLP",
|
|
"SLP_SUS", "DELETED"};
|
|
klist_t *taskhead = &g_kobj_list.task_head;
|
|
klist_t *taskend = taskhead;
|
|
klist_t *tmp;
|
|
ktask_t *task;
|
|
ktask_t *candidate;
|
|
char yes = 'N';
|
|
char *printbuf = NULL;
|
|
char tmpbuf[256] = {0};
|
|
int offset = 0;
|
|
int totallen = 2048;
|
|
int taskstate = 0;
|
|
|
|
printbuf = aos_malloc(totallen);
|
|
if (printbuf == NULL)
|
|
{
|
|
return RHINO_NO_MEM;
|
|
}
|
|
memset(printbuf, 0, totallen);
|
|
|
|
krhino_sched_disable();
|
|
preferred_cpu_ready_task_get(&g_ready_queue, cpu_cur_get());
|
|
candidate = g_preferred_ready_task[cpu_cur_get()];
|
|
|
|
snprintf(tmpbuf, 255,
|
|
"%s------------------------------------------------------------------------\r\n",
|
|
esc_tag);
|
|
safesprintf(printbuf, totallen, offset, tmpbuf);
|
|
|
|
#if (RHINO_CONFIG_CPU_USAGE_STATS > 0)
|
|
snprintf(tmpbuf, 255, "%sCPU usage :%-10d \n",
|
|
esc_tag, g_cpu_usage / 100);
|
|
safesprintf(printbuf, totallen, offset, tmpbuf);
|
|
snprintf(tmpbuf, 255,
|
|
"%s------------------------------------------------------------------------\r\n",
|
|
esc_tag);
|
|
safesprintf(printbuf, totallen, offset, tmpbuf);
|
|
|
|
#endif
|
|
snprintf(tmpbuf, 255,
|
|
"%sName State Prio StackSize MinFreesize Runtime Candidate\r\n",
|
|
esc_tag);
|
|
safesprintf(printbuf, totallen, offset, tmpbuf);
|
|
snprintf(tmpbuf, 255,
|
|
"%s------------------------------------------------------------------------\r\n",
|
|
esc_tag);
|
|
safesprintf(printbuf, totallen, offset, tmpbuf);
|
|
|
|
for (tmp = taskhead->next; tmp != taskend; tmp = tmp->next)
|
|
{
|
|
task = krhino_list_entry(tmp, ktask_t, task_stats_item);
|
|
const name_t *task_name;
|
|
rst = krhino_task_stack_min_free(task, &free_size);
|
|
|
|
if (rst != RHINO_SUCCESS)
|
|
{
|
|
free_size = 0;
|
|
}
|
|
|
|
#if (RHINO_CONFIG_TASK_SCHED_STATS > 0)
|
|
time_total = (sys_time_t)(task->task_time_total_run / 20);
|
|
#endif
|
|
|
|
if (task->task_name != NULL)
|
|
{
|
|
task_name = task->task_name;
|
|
}
|
|
else
|
|
{
|
|
task_name = "anonym";
|
|
}
|
|
|
|
if (candidate == task)
|
|
{
|
|
yes = 'Y';
|
|
}
|
|
else
|
|
{
|
|
yes = 'N';
|
|
}
|
|
|
|
taskstate = task->task_state >= sizeof(cpu_stat) / sizeof(cpu_stat[0]) ? 0 : task->task_state;
|
|
|
|
#ifndef HAVE_NOT_ADVANCED_FORMATE
|
|
snprintf(tmpbuf, 255, "%s%-19.18s%-9s%-5d%-10d%-12zu%-9llu%-11c\r\n",
|
|
esc_tag, task_name, cpu_stat[taskstate], task->prio,
|
|
task->stack_size, free_size, (unsigned long long)time_total, yes);
|
|
#else
|
|
char name_cut[19];
|
|
/* if not support %-N.Ms,cut it manually */
|
|
if (strlen(task_name) > 18)
|
|
{
|
|
memset(name_cut, 0, sizeof(name_cut));
|
|
memcpy(name_cut, task->task_name, 18);
|
|
task_name = name_cut;
|
|
}
|
|
|
|
snprintf(tmpbuf, 255, "%s%-19s%-9s%-5d%-10d%-12u%-9u%-11c\r\n",
|
|
esc_tag, task_name, cpu_stat[taskstate], task->prio,
|
|
task->stack_size, free_size, (unsigned int)time_total, yes);
|
|
#endif
|
|
safesprintf(printbuf, totallen, offset, tmpbuf);
|
|
|
|
#if 0
|
|
/* for chip not support stack frame interface,do nothing*/
|
|
if (detail == true && task != krhino_cur_task_get() && soc_get_first_frame_info &&
|
|
soc_get_subs_frame_info) {
|
|
depth = RHINO_BACKTRACE_DEPTH;
|
|
snprintf(tmpbuf, 255, "%sTask %s Call Stack Dump:\r\n", esc_tag, task_name);
|
|
safesprintf(printbuf, totallen, offset, tmpbuf);
|
|
c_frame = (size_t)task->task_stack;
|
|
soc_get_first_frame_info(c_frame, &n_frame, &pc);
|
|
|
|
for (; (n_frame != 0) && (pc != 0) && (depth >= 0); --depth) {
|
|
|
|
snprintf(tmpbuf, 255, "%sPC:0x%-12xSP:0x%-12x\r\n", esc_tag, c_frame, pc);
|
|
safesprintf(printbuf, totallen, offset, tmpbuf);
|
|
c_frame = n_frame;
|
|
soc_get_subs_frame_info(c_frame, &n_frame, &pc);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
snprintf(tmpbuf, 255,
|
|
"%s------------------------------------------------------------------------\r\n",
|
|
esc_tag);
|
|
safesprintf(printbuf, totallen, offset, tmpbuf);
|
|
krhino_sched_enable();
|
|
|
|
csp_printf("%s", printbuf);
|
|
aos_free(printbuf);
|
|
return RHINO_SUCCESS;
|
|
}
|
|
|
|
#if (RHINO_CONFIG_CPU_USAGE_STATS > 0) || (RHINO_CONFIG_DISABLE_SCHED_STATS > 0) || (RHINO_CONFIG_DISABLE_INTRPT_STATS > 0)
|
|
static uint32_t dumpsys_info_func(char *buf, uint32_t len)
|
|
{
|
|
int16_t plen = 0;
|
|
|
|
plen += sprintf(buf + plen, "%s---------------------------------------------\r\n", esc_tag);
|
|
#if (RHINO_CONFIG_CPU_USAGE_STATS > 0)
|
|
plen += sprintf(buf + plen, "%sCPU usage :%-10d \r\n", esc_tag,
|
|
g_cpu_usage / 100);
|
|
#endif
|
|
|
|
#if (RHINO_CONFIG_DISABLE_SCHED_STATS > 0)
|
|
plen += sprintf(buf + plen, "%sMax sched disable time :%-10d\r\n", esc_tag,
|
|
g_sched_disable_max_time);
|
|
#else
|
|
plen += sprintf(buf + plen, "%sMax sched disable time :%-10d\r\n", esc_tag, 0);
|
|
#endif
|
|
|
|
#if (RHINO_CONFIG_DISABLE_INTRPT_STATS > 0)
|
|
plen += sprintf(buf + plen, "%sMax intrpt disable time :%-10d\r\n", esc_tag,
|
|
g_intrpt_disable_max_time);
|
|
#else
|
|
plen += sprintf(buf + plen, "%sMax intrpt disable time :%-10d\r\n", esc_tag, 0);
|
|
#endif
|
|
|
|
plen += sprintf(buf + plen, "%s---------------------------------------------\r\n", esc_tag);
|
|
|
|
return RHINO_SUCCESS;
|
|
}
|
|
#endif
|
|
|
|
#if (RHINO_CONFIG_MM_LEAKCHECK > 0)
|
|
|
|
uint32_t dumpsys_mm_leak_func(char *buf, uint32_t len)
|
|
{
|
|
dump_mmleak();
|
|
return RHINO_SUCCESS;
|
|
}
|
|
|
|
uint8_t mm_leak_timer_cb(void *timer, void *arg)
|
|
{
|
|
dumpsys_mm_info_func(0);
|
|
return 0;
|
|
}
|
|
|
|
uint32_t dumpsys_mm_leak_check_func(char *pcWriteBuffer, int xWriteBufferLen,
|
|
int argc, char **argv)
|
|
{
|
|
static uint32_t run_flag = 0;
|
|
sys_time_t round_sec = MM_LEAK_CHECK_ROUND_SCOND;
|
|
|
|
if (argc > 2 && 0 == strcmp(argv[2], "start"))
|
|
{
|
|
if (0 == run_flag)
|
|
{
|
|
if (argc > 3 && NULL != argv[3])
|
|
{
|
|
round_sec = atoi(argv[3]) * 1000;
|
|
}
|
|
|
|
krhino_timer_create(&g_mm_leak_check_timer, "mm_leak_check_timer",
|
|
(timer_cb_t)mm_leak_timer_cb,
|
|
10, krhino_ms_to_ticks(round_sec), NULL, 0);
|
|
}
|
|
else
|
|
{
|
|
if (NULL != argv[3])
|
|
{
|
|
round_sec = atoi(argv[3]) * 1000;
|
|
|
|
if (1 == run_flag)
|
|
{
|
|
krhino_timer_stop(&g_mm_leak_check_timer);
|
|
}
|
|
|
|
krhino_timer_change(&g_mm_leak_check_timer, 10, krhino_ms_to_ticks(round_sec));
|
|
}
|
|
}
|
|
|
|
run_flag = 1;
|
|
krhino_timer_start(&g_mm_leak_check_timer);
|
|
}
|
|
|
|
if (argc > 2 && 0 == strcmp(argv[2], "stop"))
|
|
{
|
|
krhino_timer_stop(&g_mm_leak_check_timer);
|
|
run_flag = 2;
|
|
}
|
|
|
|
return RHINO_SUCCESS;
|
|
}
|
|
#endif
|
|
|
|
uint32_t dumpsys_func(char *pcWriteBuffer, int xWriteBufferLen, int argc,
|
|
char **argv)
|
|
{
|
|
uint32_t ret;
|
|
|
|
if (argc >= 2 && 0 == strcmp(argv[1], "task"))
|
|
{
|
|
if (argc == 3 && (0 == strcmp(argv[2], "detail")))
|
|
{
|
|
ret = dumpsys_task_func(pcWriteBuffer, xWriteBufferLen, true);
|
|
}
|
|
else
|
|
{
|
|
ret = dumpsys_task_func(pcWriteBuffer, xWriteBufferLen, false);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
#ifndef CSP_LINUXHOST
|
|
else if (argc >= 2 && 0 == strcmp(argv[1], "task_stack"))
|
|
{
|
|
if (argc == 3)
|
|
{
|
|
ret = dump_task_stack_byname(argv[2]);
|
|
}
|
|
else
|
|
{
|
|
ret = dump_task_stack_byname((char *)krhino_cur_task_get()->task_name);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
#if (RHINO_CONFIG_CPU_USAGE_STATS > 0) || (RHINO_CONFIG_DISABLE_SCHED_STATS > 0) || (RHINO_CONFIG_DISABLE_INTRPT_STATS > 0)
|
|
else if (argc == 2 && 0 == strcmp(argv[1], "info"))
|
|
{
|
|
ret = dumpsys_info_func(pcWriteBuffer, xWriteBufferLen);
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
#if (RHINO_CONFIG_MM_DEBUG > 0)
|
|
else if (argc == 2 && 0 == strcmp(argv[1], "mm_info"))
|
|
{
|
|
ret = dumpsys_mm_info_func(0);
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
#if (RHINO_CONFIG_MM_LEAKCHECK > 0)
|
|
else if (argc == 2 && 0 == strcmp(argv[1], "mm_leak"))
|
|
{
|
|
ret = dumpsys_mm_leak_func(NULL, 0);
|
|
return ret;
|
|
}
|
|
else if (argc > 2 && 0 == strcmp(argv[1], "mm_monitor"))
|
|
{
|
|
ret = dumpsys_mm_leak_check_func(pcWriteBuffer, xWriteBufferLen, argc, argv);
|
|
return ret;
|
|
}
|
|
#endif
|
|
else
|
|
{
|
|
int len = 0;
|
|
len += snprintf(pcWriteBuffer + len, xWriteBufferLen - len,
|
|
"%sdumpsys help:\r\n", esc_tag);
|
|
len += snprintf(pcWriteBuffer + len, xWriteBufferLen - len,
|
|
"%s\tdumpsys task : show the task info.\r\n", esc_tag);
|
|
#ifndef CSP_LINUXHOST
|
|
len += snprintf(pcWriteBuffer + len, xWriteBufferLen - len,
|
|
"%s\tdumpsys task_stack : show the task stack info.\r\n", esc_tag);
|
|
#endif
|
|
len += snprintf(pcWriteBuffer + len, xWriteBufferLen - len,
|
|
"%s\tdumpsys mm_info : show the memory has alloced.\r\n", esc_tag);
|
|
#if (RHINO_CONFIG_MM_LEAKCHECK > 0)
|
|
len += snprintf(pcWriteBuffer + len, xWriteBufferLen - len,
|
|
"%s\tdumpsys mm_leak : show the memory maybe leak.\r\n", esc_tag);
|
|
len += snprintf(pcWriteBuffer + len, xWriteBufferLen - len,
|
|
"%s\tdumpsys mm_monitor : [start/stop] [round time] fire a timer"
|
|
"to monitor mm, default 10s.\r\n",
|
|
esc_tag);
|
|
#endif
|
|
#if (RHINO_CONFIG_CPU_USAGE_STATS > 0)
|
|
len += snprintf(pcWriteBuffer + len, xWriteBufferLen - len,
|
|
"%s\tdumpsys info : show the system info\r\n", esc_tag);
|
|
#endif
|
|
return RHINO_SUCCESS;
|
|
}
|
|
}
|
|
|
|
int dump_task_stack(ktask_t *task)
|
|
{
|
|
uint32_t offset = 0;
|
|
kstat_t rst = RHINO_SUCCESS;
|
|
void *cur, *end;
|
|
int i = 0;
|
|
int *p;
|
|
char tmp[256] = {0};
|
|
|
|
char *printbuf = NULL;
|
|
char tmpbuf[256] = {0};
|
|
int bufoffset = 0;
|
|
int totallen = 2048;
|
|
|
|
printbuf = aos_malloc(totallen);
|
|
if (printbuf == NULL)
|
|
{
|
|
return RHINO_NO_MEM;
|
|
}
|
|
memset(printbuf, 0, totallen);
|
|
krhino_sched_disable();
|
|
|
|
end = task->task_stack_base + task->stack_size;
|
|
|
|
rst = krhino_task_stack_cur_free(task, &offset);
|
|
if (rst == RHINO_SUCCESS)
|
|
{
|
|
cur = task->task_stack_base + task->stack_size - offset;
|
|
}
|
|
else
|
|
{
|
|
k_err_proc(RHINO_SYS_SP_ERR);
|
|
aos_free(printbuf);
|
|
krhino_sched_enable();
|
|
return 1;
|
|
}
|
|
p = (int *)cur;
|
|
while (p < (int *)end)
|
|
{
|
|
if (i % 4 == 0)
|
|
{
|
|
sprintf(tmp, "%s\r\n%08x:", esc_tag, (uint32_t)p);
|
|
safesprintf(printbuf, totallen, bufoffset, tmp);
|
|
}
|
|
sprintf(tmp, "%s%08x ", esc_tag, *p);
|
|
safesprintf(printbuf, totallen, bufoffset, tmp);
|
|
i++;
|
|
p++;
|
|
}
|
|
snprintf(tmpbuf, 255, "%s\r\n-----------------end----------------\r\n\r\n", esc_tag);
|
|
safesprintf(printbuf, totallen, offset, tmpbuf);
|
|
krhino_sched_enable();
|
|
|
|
csp_printf("%s", printbuf);
|
|
aos_free(printbuf);
|
|
return 0;
|
|
}
|
|
|
|
int dump_task_stack_byname(char *taskname)
|
|
{
|
|
klist_t *taskhead = &g_kobj_list.task_head;
|
|
klist_t *taskend = taskhead;
|
|
klist_t *tmp;
|
|
ktask_t *task;
|
|
int printall = 0;
|
|
|
|
if (strcmp(taskname, "all") == 0)
|
|
{
|
|
printall = 1;
|
|
}
|
|
|
|
for (tmp = taskhead->next; tmp != taskend; tmp = tmp->next)
|
|
{
|
|
task = krhino_list_entry(tmp, ktask_t, task_stats_item);
|
|
if (printall == 1 || strcmp(taskname, task->task_name) == 0)
|
|
{
|
|
csp_printf("%s------task %s stack -------", esc_tag, task->task_name);
|
|
dump_task_stack(task);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void task_cmd(char *buf, int len, int argc, char **argv)
|
|
{
|
|
dumpsys_task_func(NULL, 0, 1);
|
|
}
|
|
|
|
static void dumpsys_cmd(char *buf, int len, int argc, char **argv)
|
|
{
|
|
dumpsys_func(buf, len, argc, argv);
|
|
}
|
|
|
|
struct cli_command dumpsys_cli_cmd[] = {
|
|
{"tasklist", "list all thread info", task_cmd},
|
|
{"dumpsys", "dump system info", dumpsys_cmd},
|
|
};
|
|
|
|
void dumpsys_cli_init(void)
|
|
{
|
|
aos_cli_register_commands(&dumpsys_cli_cmd[0], sizeof(dumpsys_cli_cmd) / sizeof(struct cli_command));
|
|
}
|
|
|
|
#endif
|