324 lines
11 KiB
C
324 lines
11 KiB
C
/*
|
|
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
|
|
* Copyright (c) 2020-2021 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_task_pri.h"
|
|
|
|
|
|
#ifdef LOSCFG_KERNEL_SCHED_STATISTICS
|
|
#define HIGHTASKPRI 16
|
|
#define NS_PER_MS 1000000
|
|
#define DECIMAL_TO_PERCENTAGE 100
|
|
|
|
typedef struct {
|
|
UINT64 idleRuntime;
|
|
UINT64 idleStarttime;
|
|
UINT64 highTaskRuntime;
|
|
UINT64 highTaskStarttime;
|
|
UINT64 spinWaitRuntime;
|
|
UINT64 sumPriority;
|
|
UINT32 prioritySwitch;
|
|
UINT32 highTaskSwitch;
|
|
UINT32 contexSwitch;
|
|
UINT32 hwiNum;
|
|
UINT32 ipiIrqNum;
|
|
} MpStatPercpu;
|
|
|
|
STATIC BOOL g_mpStaticStartFlag = FALSE;
|
|
STATIC UINT64 g_mpStaticStartTime;
|
|
STATIC MpStatPercpu g_mpStatPercpu[LOSCFG_KERNEL_SMP_CORE_NUM] = {0};
|
|
|
|
STATIC VOID OsMpSchedStatistics(LosTaskCB *runTask, LosTaskCB *newTask)
|
|
{
|
|
UINT32 cpuid;
|
|
UINT32 idleTaskID;
|
|
UINT64 now, runtime;
|
|
|
|
if (g_mpStaticStartFlag != TRUE) {
|
|
return;
|
|
}
|
|
|
|
cpuid = ArchCurrCpuid();
|
|
idleTaskID = OsGetIdleTaskId();
|
|
now = LOS_CurrNanosec();
|
|
|
|
g_mpStatPercpu[cpuid].contexSwitch++;
|
|
|
|
if ((runTask->taskID != idleTaskID) && (newTask->taskID == idleTaskID)) {
|
|
g_mpStatPercpu[cpuid].idleStarttime = now;
|
|
}
|
|
|
|
if ((runTask->taskID == idleTaskID) && (newTask->taskID != idleTaskID)) {
|
|
runtime = now - g_mpStatPercpu[cpuid].idleStarttime;
|
|
g_mpStatPercpu[cpuid].idleRuntime += runtime;
|
|
g_mpStatPercpu[cpuid].idleStarttime = 0;
|
|
}
|
|
|
|
if ((runTask->priority >= HIGHTASKPRI) && (newTask->priority < HIGHTASKPRI)) {
|
|
g_mpStatPercpu[cpuid].highTaskStarttime = now;
|
|
}
|
|
|
|
if ((runTask->priority < HIGHTASKPRI) && (newTask->priority >= HIGHTASKPRI)) {
|
|
runtime = now - g_mpStatPercpu[cpuid].highTaskStarttime;
|
|
g_mpStatPercpu[cpuid].highTaskRuntime += runtime;
|
|
g_mpStatPercpu[cpuid].highTaskStarttime = 0;
|
|
}
|
|
|
|
if (newTask->priority < HIGHTASKPRI) {
|
|
g_mpStatPercpu[cpuid].highTaskSwitch++;
|
|
}
|
|
|
|
if (newTask->taskID != idleTaskID) {
|
|
g_mpStatPercpu[cpuid].sumPriority += newTask->priority;
|
|
g_mpStatPercpu[cpuid].prioritySwitch++;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
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;
|
|
OsMpSchedStatistics(runTask, newTask);
|
|
}
|
|
|
|
LITE_OS_SEC_TEXT_MINOR VOID OsSpinWaitStatistics(UINT64 spinWaitRuntime)
|
|
{
|
|
UINT32 cpuid = ArchCurrCpuid();
|
|
g_mpStatPercpu[cpuid].spinWaitRuntime += spinWaitRuntime;
|
|
return;
|
|
}
|
|
|
|
LITE_OS_SEC_TEXT_MINOR VOID OsHwiStatistics(size_t intNum)
|
|
{
|
|
UINT32 cpuid = ArchCurrCpuid();
|
|
|
|
if ((g_mpStaticStartFlag != TRUE) || (intNum == OS_TICK_INT_NUM)) {
|
|
return;
|
|
}
|
|
|
|
g_mpStatPercpu[cpuid].hwiNum++;
|
|
/* 16: 0~15 is ipi interrupts */
|
|
if (intNum < 16) {
|
|
g_mpStatPercpu[cpuid].ipiIrqNum++;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
LITE_OS_SEC_TEXT_MINOR VOID OsShellCmdDumpSched(VOID)
|
|
{
|
|
LosTaskCB *taskCB = NULL;
|
|
UINT32 loop;
|
|
UINT32 cpuid;
|
|
UINT32 affinity;
|
|
|
|
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 (OsTaskIsUnused(taskCB)) {
|
|
continue;
|
|
}
|
|
|
|
affinity = (UINT32)taskCB->cpuAffiMask;
|
|
|
|
PRINTK("%-30s0x%-6x%+16lf ms %10d\n", taskCB->taskName, taskCB->taskID,
|
|
(DOUBLE)(taskCB->schedStat.allRuntime) / NS_PER_MS,
|
|
taskCB->schedStat.allContextSwitch);
|
|
|
|
for (cpuid = 0; cpuid < LOSCFG_KERNEL_CORE_NUM; cpuid++) {
|
|
if (!((1U << cpuid) & affinity)) {
|
|
continue;
|
|
}
|
|
|
|
PRINTK(" "
|
|
"CPU%d %+16lf ms %12d\n", cpuid,
|
|
(DOUBLE)(taskCB->schedStat.schedPercpu[cpuid].runtime) / NS_PER_MS,
|
|
taskCB->schedStat.schedPercpu[cpuid].contexSwitch);
|
|
}
|
|
}
|
|
|
|
PRINTK("\n");
|
|
}
|
|
|
|
LITE_OS_SEC_TEXT_MINOR VOID OsShellMpStaticStart(VOID)
|
|
{
|
|
LosTaskCB *taskCB = NULL;
|
|
UINT32 loop;
|
|
UINT32 cpuid = 0;
|
|
UINT32 intSave;
|
|
|
|
SCHEDULER_LOCK(intSave);
|
|
|
|
if (g_mpStaticStartFlag) {
|
|
PRINT_WARN("mp static has started\n");
|
|
SCHEDULER_UNLOCK(intSave);
|
|
return;
|
|
}
|
|
|
|
g_mpStaticStartTime = 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, "Idle")) {
|
|
g_mpStatPercpu[cpuid].idleStarttime = g_mpStaticStartTime;
|
|
}
|
|
if (taskCB->priority < HIGHTASKPRI) {
|
|
g_mpStatPercpu[cpuid].highTaskStarttime = g_mpStaticStartTime;
|
|
g_mpStatPercpu[cpuid].highTaskSwitch++;
|
|
}
|
|
if (strcmp(taskCB->taskName, "Idle")) {
|
|
g_mpStatPercpu[cpuid].sumPriority += taskCB->priority;
|
|
g_mpStatPercpu[cpuid].prioritySwitch++;
|
|
}
|
|
}
|
|
}
|
|
g_mpStaticStartFlag = TRUE;
|
|
SCHEDULER_UNLOCK(intSave);
|
|
|
|
PRINTK("mp static start\n");
|
|
|
|
return;
|
|
}
|
|
|
|
LITE_OS_SEC_TEXT_MINOR VOID OsMpStaticShow(UINT64 mpStaticPastTime)
|
|
{
|
|
UINT32 cpuid;
|
|
PRINTK("\n");
|
|
PRINTK("Passed Time: %+16lf ms\n", (DOUBLE)mpStaticPastTime / NS_PER_MS);
|
|
PRINTK("--------------------------------\n");
|
|
PRINTK("CPU Idle(%%) schedule noTick Hwi MP Hwi MP Loss(%%) "
|
|
"avg PRI HiTSK(%%) HiTSK SCH HiTSK P(ms)\n");
|
|
PRINTK("---- --------- ---------- ---------- ---------- ---------- "
|
|
"---------- ---------- ---------- ----------\n");
|
|
|
|
for (cpuid = 0; cpuid < LOSCFG_KERNEL_CORE_NUM; cpuid++) {
|
|
PRINTK("CPU%d %+10lf%14d%14d%14d %+11lf %+11lf %+11lf%14d %+11lf\n", cpuid,
|
|
((DOUBLE)(g_mpStatPercpu[cpuid].idleRuntime) / mpStaticPastTime) * DECIMAL_TO_PERCENTAGE,
|
|
g_mpStatPercpu[cpuid].contexSwitch,
|
|
g_mpStatPercpu[cpuid].hwiNum,
|
|
g_mpStatPercpu[cpuid].ipiIrqNum,
|
|
((DOUBLE)(g_mpStatPercpu[cpuid].spinWaitRuntime) / mpStaticPastTime) * DECIMAL_TO_PERCENTAGE,
|
|
(g_mpStatPercpu[cpuid].prioritySwitch == 0) ? OS_TASK_PRIORITY_LOWEST :
|
|
((DOUBLE)(g_mpStatPercpu[cpuid].sumPriority) / (g_mpStatPercpu[cpuid].prioritySwitch)),
|
|
((DOUBLE)(g_mpStatPercpu[cpuid].highTaskRuntime) / mpStaticPastTime) * DECIMAL_TO_PERCENTAGE,
|
|
g_mpStatPercpu[cpuid].highTaskSwitch,
|
|
(g_mpStatPercpu[cpuid].highTaskSwitch == 0) ? 0 :
|
|
((DOUBLE)(g_mpStatPercpu[cpuid].highTaskRuntime) / (g_mpStatPercpu[cpuid].highTaskSwitch)) / NS_PER_MS);
|
|
}
|
|
|
|
PRINTK("\n");
|
|
}
|
|
|
|
LITE_OS_SEC_TEXT_MINOR VOID OsShellMpStaticStop(VOID)
|
|
{
|
|
LosTaskCB *taskCB = NULL;
|
|
UINT32 loop;
|
|
UINT32 cpuid = 0;
|
|
UINT64 mpStaticStopTime;
|
|
UINT64 mpStaticPastTime;
|
|
UINT64 runtime;
|
|
UINT32 intSave;
|
|
|
|
SCHEDULER_LOCK(intSave);
|
|
|
|
if (g_mpStaticStartFlag != TRUE) {
|
|
PRINT_WARN("Please set mp static start\n");
|
|
SCHEDULER_UNLOCK(intSave);
|
|
return;
|
|
}
|
|
|
|
g_mpStaticStartFlag = FALSE;
|
|
mpStaticStopTime = LOS_CurrNanosec();
|
|
mpStaticPastTime = mpStaticStopTime - g_mpStaticStartTime;
|
|
|
|
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, "Idle")) {
|
|
runtime = mpStaticStopTime - g_mpStatPercpu[cpuid].idleStarttime;
|
|
g_mpStatPercpu[cpuid].idleRuntime += runtime;
|
|
g_mpStatPercpu[cpuid].idleStarttime = 0;
|
|
}
|
|
if (taskCB->priority < HIGHTASKPRI) {
|
|
runtime = mpStaticStopTime - g_mpStatPercpu[cpuid].highTaskStarttime;
|
|
g_mpStatPercpu[cpuid].highTaskRuntime += runtime;
|
|
g_mpStatPercpu[cpuid].highTaskStarttime = 0;
|
|
}
|
|
}
|
|
}
|
|
SCHEDULER_UNLOCK(intSave);
|
|
OsMpStaticShow(mpStaticPastTime);
|
|
|
|
(VOID)memset_s(g_mpStatPercpu, sizeof(g_mpStatPercpu), 0, sizeof(g_mpStatPercpu));
|
|
g_mpStaticStartTime = 0;
|
|
return;
|
|
}
|
|
|
|
#endif
|
|
|