diff --git a/components/debugtools/BUILD.gn b/components/debugtools/BUILD.gn index 3a79bcc9..5ff7d865 100644 --- a/components/debugtools/BUILD.gn +++ b/components/debugtools/BUILD.gn @@ -33,6 +33,7 @@ module_name = get_path_info(rebase_path("."), "name") kernel_module(module_name) { sources = [ "los_hwidump.c", + "los_schedtrace.c", "los_stackdump.c", ] configs += [ "$LITEOSTOPDIR:warn_config" ] diff --git a/components/debugtools/los_debugtools.h b/components/debugtools/los_debugtools.h index de03c64b..231e63a7 100644 --- a/components/debugtools/los_debugtools.h +++ b/components/debugtools/los_debugtools.h @@ -40,17 +40,46 @@ extern "C" { #endif /* __cplusplus */ #endif /* __cplusplus */ + +/* StackDump print format */ #define PRINT_PER_ROW 4 -/* Shell Callback */ +/* SchedTrace records number */ +#define TRACE_NUM 200 + +/* sched trace info, users can add their own */ +typedef struct { + UINT32 newTaskID; + CHAR newTaskName[LOS_TASK_NAMELEN]; + UINT32 runTaskID; + CHAR runTaskName[LOS_TASK_NAMELEN]; +} SchedTraceInfo; + +/* SchedTrace record callback */ +typedef void (*SchedTraceRecordCB)(LosTaskCB *newTask, LosTaskCB *runTask); + +/* SchedTrace show callback, buf is overwrite ringbuf, max amount of storage is TRACE_NUM */ +typedef void (*SchedTraceShowCB)(SchedTraceInfo *ringBuf, UINT32 count); + +/* Shell callback */ extern UINT32 OsShellCmdStackDump(INT32 argc, const CHAR **argv); extern UINT32 OsShellCmdHwiDump(INT32 argc, const CHAR **argv); +extern UINT32 OsShellCmdSchedTrace(INT32 argc, const CHAR **argv); -/* other module Callback */ +/* Other module callback */ +extern VOID OsSchedTraceRecord(LosTaskCB *newTask, LosTaskCB *runTask); -/* External Interface */ +/* External interface */ +/* dump stack by task id, can be called at any time */ extern VOID LOS_TaskStackDump(UINT32 taskID); +/* register sched trace handle, If not registered, the default fun will be used */ +extern VOID LOS_SchedTraceHandleRegister(SchedTraceRecordCB recordCB, SchedTraceShowCB showCB); +/* start sched trace, will alloc buf, and start write to buf when sched */ +extern VOID LOS_SchedTraceStart(VOID); +/* stop sched trace, will stop record and free buf */ +extern VOID LOS_SchedTraceStop(VOID); + #ifdef __cplusplus #if __cplusplus } diff --git a/components/debugtools/los_schedtrace.c b/components/debugtools/los_schedtrace.c new file mode 100644 index 00000000..7de17e59 --- /dev/null +++ b/components/debugtools/los_schedtrace.c @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2022-2022 Huawei Device Co., Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "los_debugtools.h" +#include "securec.h" +#include "los_debug.h" +#include "los_memory.h" +#include "los_arch.h" + +#if (LOSCFG_DEBUG_TOOLS == 1) +STATIC BOOL g_startTrace = FALSE; +STATIC SchedTraceInfo *g_traceRingBuf = NULL; +STATIC UINT32 g_schedCount = 0; +STATIC SchedTraceRecordCB g_recordCB = NULL; +STATIC SchedTraceShowCB g_showCB = NULL; + +STATIC VOID DefaultShowFormat(SchedTraceInfo *buf, UINT32 count) +{ + INT32 i; + UINT32 cycle = count / TRACE_NUM; + UINT32 point = count % TRACE_NUM; + + PRINTK ("sched %u time, last %u is:\r\n", count, TRACE_NUM); + PRINTK("RunTaskID RunTaskName NewTaskID NewTaskName \r\n"); + if (cycle > 0) { + for (i = point; i < TRACE_NUM; i++) { + PRINTK("%4u %20s, %4u %20s\n", + g_traceRingBuf[i].runTaskID, g_traceRingBuf[i].runTaskName, + g_traceRingBuf[i].newTaskID, g_traceRingBuf[i].newTaskName); + } + } + + for (i = 0; i < point; i++) { + PRINTK("%4u %20s, %4u %20s\n", + g_traceRingBuf[i].runTaskID, g_traceRingBuf[i].runTaskName, + g_traceRingBuf[i].newTaskID, g_traceRingBuf[i].newTaskName); + } + + PRINTK("\r\n"); +} + +STATIC VOID DefaultRecordHandle(LosTaskCB *newTask, LosTaskCB *runTask) +{ + UINT32 point = g_schedCount % TRACE_NUM; + + g_traceRingBuf[point].newTaskID = newTask->taskID; + (VOID)memcpy_s(g_traceRingBuf[point].newTaskName, LOS_TASK_NAMELEN, newTask->taskName, LOS_TASK_NAMELEN); + g_traceRingBuf[point].runTaskID = runTask->taskID; + (VOID)memcpy_s(g_traceRingBuf[point].runTaskName, LOS_TASK_NAMELEN, runTask->taskName, LOS_TASK_NAMELEN); + + g_schedCount++; +} + +STATIC VOID ShowFormat(SchedTraceInfo *buf, UINT32 count) +{ + if (count == 0) { + PRINT_ERR("none shed happend\n"); + return; + } + + if (g_showCB != NULL) { + g_showCB(buf, count); + } +} + +VOID OsSchedTraceRecord(LosTaskCB *newTask, LosTaskCB *runTask) +{ + if (g_startTrace == FALSE) { + return; + } + + if (g_recordCB != NULL) { + g_recordCB(newTask, runTask); + } +} + +VOID LOS_SchedTraceStart(VOID) +{ + if (g_recordCB == NULL) { + g_recordCB = DefaultRecordHandle; + } + + g_traceRingBuf = (SchedTraceInfo *)LOS_MemAlloc(OS_SYS_MEM_ADDR, TRACE_NUM * sizeof(SchedTraceInfo)); + if (g_traceRingBuf == NULL) { + PRINT_ERR("alloc failed for dump\n"); + return; + } + (VOID)memset_s(g_traceRingBuf, TRACE_NUM * sizeof(SchedTraceInfo), 0, TRACE_NUM * sizeof(SchedTraceInfo)); + + g_startTrace = TRUE; +} + +VOID LOS_SchedTraceStop(VOID) +{ + if (g_showCB == NULL) { + g_showCB = DefaultShowFormat; + } + g_startTrace = FALSE; + ShowFormat(g_traceRingBuf, g_schedCount); + g_schedCount = 0; + + (VOID)LOS_MemFree(OS_SYS_MEM_ADDR, g_traceRingBuf); + g_traceRingBuf = NULL; + + return; +} + +VOID LOS_SchedTraceHandleRegister(SchedTraceRecordCB recordCB, SchedTraceShowCB showCB) +{ + g_recordCB = recordCB; + g_showCB = showCB; +} + +UINT32 OsShellCmdSchedTrace(INT32 argc, const CHAR **argv) +{ + if (argc != 1) { + PRINT_ERR("\nUsage: st -h\n"); + return LOS_NOK; + } + + if (strcmp(argv[0], "-s") == 0) { + LOS_SchedTraceStart(); + } else if (strcmp(argv[0], "-e") == 0) { + LOS_SchedTraceStop(); + } else if (strcmp(argv[0], "-h") == 0) { + PRINTK("\nUsage: \nst -s , SchedTrace start\n"); + PRINTK("st -e , SchedTrace end and show\n"); + } else { + PRINTK("\nUsage: st -h\n"); + return OS_ERROR; + } + + return LOS_OK; +} +#endif /* LOSCFG_STACK_DUMP == 1 */ diff --git a/components/shell/src/base/shcmd.c b/components/shell/src/base/shcmd.c index 48b5ff73..1bd0e48f 100644 --- a/components/shell/src/base/shcmd.c +++ b/components/shell/src/base/shcmd.c @@ -69,6 +69,7 @@ CmdItem g_shellcmdAll[] = { #if (LOSCFG_DEBUG_TOOLS == 1) {CMD_TYPE_EX, "stack", 1, (CmdCallBackFunc)OsShellCmdStackDump}, {CMD_TYPE_EX, "hwi", 1, (CmdCallBackFunc)OsShellCmdHwiDump}, + {CMD_TYPE_EX, "st", 1, (CmdCallBackFunc)OsShellCmdSchedTrace}, #endif {CMD_TYPE_EX, "help", 0, (CmdCallBackFunc)OsShellCmdHelp}, }; diff --git a/kernel/src/los_sched.c b/kernel/src/los_sched.c index cb72e290..25ffe9d8 100644 --- a/kernel/src/los_sched.c +++ b/kernel/src/los_sched.c @@ -38,6 +38,9 @@ #if (LOSCFG_KERNEL_PM == 1) #include "los_pm.h" #endif +#if (LOSCFG_DEBUG_TOOLS == 1) +#include "los_debugtools.h" +#endif #ifdef __cplusplus #if __cplusplus @@ -547,6 +550,9 @@ BOOL OsSchedTaskSwitch(VOID) isTaskSwitch = TRUE; OsHookCall(LOS_HOOK_TYPE_TASK_SWITCHEDIN); +#if (LOSCFG_DEBUG_TOOLS == 1) + OsSchedTraceRecord(newTask, runTask); +#endif } OsSchedTaskDeQueue(newTask);