You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
LiteOS-Reading/debug/los_sched_debug.c

348 lines
12 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/* ----------------------------------------------------------------------------
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
* Description: Schedule Statistics
* Author: Huawei LiteOS Team
* Create: 2018-11-16
* 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_task_pri.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#ifdef LOSCFG_DEBUG_SCHED_STATISTICS
#define HIGHTASKPRI 16
#define NS_PER_MS 1000000
#define DECIMAL_TO_PERCENTAGE 100
typedef struct {
UINT64 idleRuntime; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>//
UINT64 idleStarttime; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>//
UINT64 highTaskRuntime; //<2F><><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD><C8BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>//
UINT64 highTaskStarttime; //<2F><><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD><C8BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>//
UINT64 sumPriority; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD>֮<EFBFBD><D6AE>//
UINT32 prioritySwitch; //<2F><><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><D0BB><EFBFBD><EFBFBD><EFBFBD>//
UINT32 highTaskSwitch; //<2F><><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD><C8BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><D0BB><EFBFBD><EFBFBD><EFBFBD>//
UINT32 contexSwitch; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><D0BB><EFBFBD><EFBFBD><EFBFBD>//
UINT32 hwiNum; //Ӳ<><D3B2><EFBFBD>жϴ<D0B6><CFB4><EFBFBD>//
#ifdef LOSCFG_KERNEL_SMP
UINT32 ipiIrqNum; //<2F>жϴ<D0B6><CFB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڶ<EFBFBD><DAB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><C2B6>壩//
#endif
} StatPercpu;
STATIC BOOL g_statisticsStartFlag = FALSE;
STATIC UINT64 g_statisticsStartTime;
STATIC StatPercpu g_statPercpu[LOSCFG_KERNEL_CORE_NUM];
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><C3BF> CPU <20><><EFBFBD><EFBFBD><EFBFBD>Ͻ<EFBFBD><CFBD>е<EFBFBD><D0B5><EFBFBD>ͳ<EFBFBD><CDB3>//
STATIC VOID OsSchedStatisticsPerCpu(const LosTaskCB *runTask, const LosTaskCB *newTask)
{
UINT32 cpuId;
UINT32 idleTaskId;
UINT64 now, runtime;
if (g_statisticsStartFlag != TRUE) {
return;
}
cpuId = ArchCurrCpuid();
idleTaskId = OsGetIdleTaskId();
now = LOS_CurrNanosec();
g_statPercpu[cpuId].contexSwitch++;
if ((runTask->taskId != idleTaskId) && (newTask->taskId == idleTaskId)) {
g_statPercpu[cpuId].idleStarttime = now;
}
if ((runTask->taskId == idleTaskId) && (newTask->taskId != idleTaskId)) {
runtime = now - g_statPercpu[cpuId].idleStarttime;
g_statPercpu[cpuId].idleRuntime += runtime;
g_statPercpu[cpuId].idleStarttime = 0;
}
if ((runTask->priority >= HIGHTASKPRI) && (newTask->priority < HIGHTASKPRI)) {
g_statPercpu[cpuId].highTaskStarttime = now;
}
if ((runTask->priority < HIGHTASKPRI) && (newTask->priority >= HIGHTASKPRI)) {
runtime = now - g_statPercpu[cpuId].highTaskStarttime;
g_statPercpu[cpuId].highTaskRuntime += runtime;
g_statPercpu[cpuId].highTaskStarttime = 0;
}
if (newTask->priority < HIGHTASKPRI) {
g_statPercpu[cpuId].highTaskSwitch++;
}
if (newTask->taskId != idleTaskId) {
g_statPercpu[cpuId].sumPriority += newTask->priority;
g_statPercpu[cpuId].prioritySwitch++;
}
return;
}
//<2F><><EFBFBD>ڸ<EFBFBD><DAB8>µ<EFBFBD><C2B5><EFBFBD>ͳ<EFBFBD><CDB3><EFBFBD><EFBFBD>Ϣ//
LITE_OS_SEC_TEXT_MINOR VOID OsSchedStatistics(LosTaskCB *runTask, LosTaskCB *newTask)
{
UINT64 runtime;
UINT32 cpuId = ArchCurrCpuid();
UINT64 now = LOS_CurrNanosec();
SchedStat *schedRun = &runTask->schedStat;
SchedStat *schedNew = &newTask->schedStat;
SchedPercpu *cpuRun = &schedRun->schedPercpu[cpuId];
SchedPercpu *cpuNew = &schedNew->schedPercpu[cpuId];
/* calculate one chance of running time */
runtime = now - schedRun->startRuntime;
/* add running timer to running task statistics */
cpuRun->runtime += runtime;
schedRun->allRuntime += runtime;
/* add context switch counters and schedule start time */
cpuNew->contexSwitch++;
schedNew->allContextSwitch++;
schedNew->startRuntime = now;
OsSchedStatisticsPerCpu(runTask, newTask);
}
LITE_OS_SEC_TEXT_MINOR VOID OsHwiStatistics(size_t intNum) //<2F><><EFBFBD>ڸ<EFBFBD><DAB8><EFBFBD>Ӳ<EFBFBD>жϵ<D0B6>ͳ<EFBFBD><CDB3><EFBFBD><EFBFBD>Ϣ//
{
UINT32 cpuId = ArchCurrCpuid();
if ((g_statisticsStartFlag != TRUE) || (intNum == OS_TICK_INT_NUM)) {
return;
}
g_statPercpu[cpuId].hwiNum++;
#ifdef LOSCFG_KERNEL_SMP
/* 16: 0~15 is ipi interrupts */
if (intNum < 16) {
g_statPercpu[cpuId].ipiIrqNum++;
}
#endif
return;
}
LITE_OS_SEC_TEXT_MINOR VOID OsShellCmdDumpSched(VOID) //<2F><><EFBFBD>ڴ<EFBFBD>ӡ<EFBFBD><D3A1><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD><C4B5><EFBFBD>ͳ<EFBFBD><CDB3><EFBFBD><EFBFBD>Ϣ//
{
LosTaskCB *taskCB = NULL;
UINT32 loop;
UINT32 cpuId;
#ifdef LOSCFG_KERNEL_SMP
UINT32 affinity;
#endif
PRINTK("\n");
PRINTK("Task TID Total Time Total CST "
"CPU Time CST\n");
PRINTK("---- --- ------------------ ---------- -"
"--- ------------------ ----------\n");
for (loop = 0; loop < g_taskMaxNum; loop++) {
taskCB = (((LosTaskCB *)g_taskCBArray) + loop);
if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
continue;
}
#ifdef LOSCFG_KERNEL_SMP
affinity = (UINT32)taskCB->cpuAffiMask;
#endif
PRINTK("%-30s0x%-6x%+16lf ms %10u\n", taskCB->taskName, taskCB->taskId,
(DOUBLE)(taskCB->schedStat.allRuntime) / NS_PER_MS,
taskCB->schedStat.allContextSwitch);
for (cpuId = 0; cpuId < LOSCFG_KERNEL_CORE_NUM; cpuId++) {
#ifdef LOSCFG_KERNEL_SMP
if (!((1U << cpuId) & affinity)) {
continue;
}
#endif
PRINTK(" "
"CPU%u %+16lf ms %12u\n", cpuId,
(DOUBLE)(taskCB->schedStat.schedPercpu[cpuId].runtime) / NS_PER_MS,
taskCB->schedStat.schedPercpu[cpuId].contexSwitch);
}
}
PRINTK("\n");
}
LITE_OS_SEC_TEXT_MINOR VOID OsStatisticsShow(UINT64 statisticsPastTime) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾϵͳ<CFB5><CDB3>ͳ<EFBFBD><CDB3><EFBFBD><EFBFBD>Ϣ//
{
UINT32 cpuId;
PRINTK("\n");
PRINTK("Passed Time: %+16lf ms\n", ((DOUBLE)statisticsPastTime / NS_PER_MS));
PRINTK("--------------------------------\n");
PRINTK("CPU Idle(%%) ContexSwitch HwiNum "
"Avg Pri HiTask(%%) HiTask SwiNum HiTask P(ms)"
#ifdef LOSCFG_KERNEL_SMP
" MP Hwi\n");
#else
"\n");
#endif
PRINTK("---- --------- ----------- -------- --------- "
"---------- ------------ ----------"
#ifdef LOSCFG_KERNEL_SMP
" ------\n");
#else
"\n");
#endif
for (cpuId = 0; cpuId < LOSCFG_KERNEL_CORE_NUM; cpuId++) {
#ifdef LOSCFG_KERNEL_SMP
PRINTK("CPU%u %+10lf%14u%14u %+11lf %+11lf%14u %+11lf %11u\n", cpuId,
#else
PRINTK("CPU%u %+10lf%14u%14u %+11lf %+11lf%14u %+11lf\n", cpuId,
#endif
((DOUBLE)(g_statPercpu[cpuId].idleRuntime) / statisticsPastTime) * DECIMAL_TO_PERCENTAGE,
g_statPercpu[cpuId].contexSwitch,
g_statPercpu[cpuId].hwiNum,
(g_statPercpu[cpuId].prioritySwitch == 0) ? OS_TASK_PRIORITY_LOWEST :
((DOUBLE)(g_statPercpu[cpuId].sumPriority) / (g_statPercpu[cpuId].prioritySwitch)),
((DOUBLE)(g_statPercpu[cpuId].highTaskRuntime) / statisticsPastTime) * DECIMAL_TO_PERCENTAGE,
g_statPercpu[cpuId].highTaskSwitch,
(g_statPercpu[cpuId].highTaskSwitch == 0) ? 0 :
((DOUBLE)(g_statPercpu[cpuId].highTaskRuntime) / (g_statPercpu[cpuId].highTaskSwitch)) / NS_PER_MS
#ifdef LOSCFG_KERNEL_SMP
, g_statPercpu[cpuId].ipiIrqNum);
#else
);
#endif
}
PRINTK("\n");
}
LITE_OS_SEC_TEXT_MINOR VOID OsShellStatisticsStart(VOID) //<2F><><EFBFBD><EFBFBD><EFBFBD>ڶ<EFBFBD><DAB6><EFBFBD>ϵͳ<CFB5><CDB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͳ<EFBFBD>ƹ<EFBFBD><C6B9><EFBFBD>//
{
LosTaskCB *taskCB = NULL;
UINT32 loop;
UINT32 cpuId = 0;
UINT32 intSave;
SCHEDULER_LOCK(intSave);
if (g_statisticsStartFlag) {
SCHEDULER_UNLOCK(intSave);
PRINT_WARN("mp static has started\n");
return;
}
g_statisticsStartTime = LOS_CurrNanosec();
for (loop = 0; loop < g_taskMaxNum; loop++) {
taskCB = (((LosTaskCB *)g_taskCBArray) + loop);
if (taskCB->taskStatus & OS_TASK_STATUS_RUNNING) {
#ifdef LOSCFG_KERNEL_SMP
cpuId = taskCB->currCpu;
#endif
if ((UINT32)(OS_TASK_INVALID_CPUID) == cpuId) {
continue;
}
if (!strcmp(taskCB->taskName, "IdleCore000")) {
g_statPercpu[cpuId].idleStarttime = g_statisticsStartTime;
}
if (taskCB->priority < HIGHTASKPRI) {
g_statPercpu[cpuId].highTaskStarttime = g_statisticsStartTime;
g_statPercpu[cpuId].highTaskSwitch++;
}
if (strcmp(taskCB->taskName, "IdleCore000")) {
g_statPercpu[cpuId].sumPriority += taskCB->priority;
g_statPercpu[cpuId].prioritySwitch++;
}
}
}
g_statisticsStartFlag = TRUE;
SCHEDULER_UNLOCK(intSave);
PRINTK("mp static start\n");
return;
}
//<2F><><EFBFBD><EFBFBD><EFBFBD>ڶ<EFBFBD><DAB6><EFBFBD>ϵͳ<CFB5><CDB3>ֹͣͳ<D6B9>ƹ<EFBFBD><C6B9>ܣ<EFBFBD><DCA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͳ<EFBFBD><CDB3><EFBFBD><EFBFBD><EFBFBD>ݵĴ<DDB5><C4B4><EFBFBD><EFBFBD><EFBFBD>չʾ//
LITE_OS_SEC_TEXT_MINOR VOID OsShellStatisticsStop(VOID)
{
LosTaskCB *taskCB = NULL;
UINT32 loop;
UINT32 cpuId = 0;
UINT64 statisticsStopTime;
UINT64 statisticsPastTime;
UINT64 runtime;
UINT32 intSave;
SCHEDULER_LOCK(intSave);
if (g_statisticsStartFlag != TRUE) {
SCHEDULER_UNLOCK(intSave);
PRINT_WARN("Please set mp static start\n");
return;
}
g_statisticsStartFlag = FALSE;
statisticsStopTime = LOS_CurrNanosec();
statisticsPastTime = statisticsStopTime - g_statisticsStartTime;
for (loop = 0; loop < g_taskMaxNum; loop++) {
taskCB = (((LosTaskCB *)g_taskCBArray) + loop);
if (taskCB->taskStatus & OS_TASK_STATUS_RUNNING) {
#ifdef LOSCFG_KERNEL_SMP
cpuId = taskCB->currCpu;
#endif
if (cpuId == (UINT32)(OS_TASK_INVALID_CPUID)) {
continue;
}
if (!strcmp(taskCB->taskName, "IdleCore000")) {
runtime = statisticsStopTime - g_statPercpu[cpuId].idleStarttime;
g_statPercpu[cpuId].idleRuntime += runtime;
g_statPercpu[cpuId].idleStarttime = 0;
}
if (taskCB->priority < HIGHTASKPRI) {
runtime = statisticsStopTime - g_statPercpu[cpuId].highTaskStarttime;
g_statPercpu[cpuId].highTaskRuntime += runtime;
g_statPercpu[cpuId].highTaskStarttime = 0;
}
}
}
SCHEDULER_UNLOCK(intSave);
OsStatisticsShow(statisticsPastTime);
(VOID)memset_s(g_statPercpu, sizeof(g_statPercpu), 0, sizeof(g_statPercpu));
g_statisticsStartTime = 0;
return;
}
#endif
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */