• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2022 Huawei Device Co., Ltd. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification,
5  * are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright notice, this list of
8  *    conditions and the following disclaimer.
9  *
10  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11  *    of conditions and the following disclaimer in the documentation and/or other materials
12  *    provided with the distribution.
13  *
14  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
15  *    to endorse or promote products derived from this software without specific prior written
16  *    permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "los_statistics_pri.h"
32 #include "los_task_pri.h"
33 #include "los_process_pri.h"
34 
35 #ifdef LOSCFG_SCHED_DEBUG
36 #ifdef LOSCFG_SCHED_TICK_DEBUG
37 typedef struct {
38     UINT64 responseTime;
39     UINT64 responseTimeMax;
40     UINT64 count;
41 } SchedTickDebug;
42 STATIC SchedTickDebug *g_schedTickDebug = NULL;
43 
OsSchedDebugInit(VOID)44 UINT32 OsSchedDebugInit(VOID)
45 {
46     UINT32 size = sizeof(SchedTickDebug) * LOSCFG_KERNEL_CORE_NUM;
47     g_schedTickDebug = (SchedTickDebug *)LOS_MemAlloc(m_aucSysMem0, size);
48     if (g_schedTickDebug == NULL) {
49         return LOS_ERRNO_TSK_NO_MEMORY;
50     }
51 
52     (VOID)memset_s(g_schedTickDebug, size, 0, size);
53     return LOS_OK;
54 }
55 
OsSchedDebugRecordData(VOID)56 VOID OsSchedDebugRecordData(VOID)
57 {
58     SchedRunqueue *rq = OsSchedRunqueue();
59     SchedTickDebug *schedDebug = &g_schedTickDebug[ArchCurrCpuid()];
60     UINT64 currTime = OsGetCurrSchedTimeCycle();
61     LOS_ASSERT(currTime >= rq->responseTime);
62     UINT64 usedTime = currTime - rq->responseTime;
63     schedDebug->responseTime += usedTime;
64     if (usedTime > schedDebug->responseTimeMax) {
65         schedDebug->responseTimeMax = usedTime;
66     }
67     schedDebug->count++;
68 }
69 
OsShellShowTickResponse(VOID)70 UINT32 OsShellShowTickResponse(VOID)
71 {
72     UINT32 intSave;
73     UINT16 cpu;
74 
75     UINT32 tickSize = sizeof(SchedTickDebug) * LOSCFG_KERNEL_CORE_NUM;
76     SchedTickDebug *schedDebug = (SchedTickDebug *)LOS_MemAlloc(m_aucSysMem1, tickSize);
77     if (schedDebug == NULL) {
78         return LOS_NOK;
79     }
80 
81     SCHEDULER_LOCK(intSave);
82     (VOID)memcpy_s((CHAR *)schedDebug, tickSize, (CHAR *)g_schedTickDebug, tickSize);
83     SCHEDULER_UNLOCK(intSave);
84 
85     PRINTK("cpu   ATRTime(us) ATRTimeMax(us)  TickCount\n");
86     for (cpu = 0; cpu < LOSCFG_KERNEL_CORE_NUM; cpu++) {
87         SchedTickDebug *schedData = &schedDebug[cpu];
88         UINT64 averTime = 0;
89         if (schedData->count > 0) {
90             averTime = schedData->responseTime / schedData->count;
91             averTime = (averTime * OS_NS_PER_CYCLE) / OS_SYS_NS_PER_US;
92         }
93         UINT64 timeMax = (schedData->responseTimeMax * OS_NS_PER_CYCLE) / OS_SYS_NS_PER_US;
94         PRINTK("%3u%14llu%15llu%11llu\n", cpu, averTime, timeMax, schedData->count);
95     }
96 
97     (VOID)LOS_MemFree(m_aucSysMem1, schedDebug);
98     return LOS_OK;
99 }
100 #endif
101 
SchedDataGet(const LosTaskCB * taskCB,UINT64 * runTime,UINT64 * timeSlice,UINT64 * pendTime,UINT64 * schedWait)102 STATIC VOID SchedDataGet(const LosTaskCB *taskCB, UINT64 *runTime, UINT64 *timeSlice,
103                          UINT64 *pendTime, UINT64 *schedWait)
104 {
105     if (taskCB->schedStat.switchCount >= 1) {
106         UINT64 averRunTime = taskCB->schedStat.runTime / taskCB->schedStat.switchCount;
107         *runTime = (averRunTime * OS_NS_PER_CYCLE) / OS_SYS_NS_PER_US;
108     }
109 
110     if (taskCB->schedStat.timeSliceCount > 1) {
111         UINT64 averTimeSlice = taskCB->schedStat.timeSliceTime / (taskCB->schedStat.timeSliceCount - 1);
112         *timeSlice = (averTimeSlice * OS_NS_PER_CYCLE) / OS_SYS_NS_PER_US;
113     }
114 
115     if (taskCB->schedStat.pendCount > 1) {
116         UINT64 averPendTime = taskCB->schedStat.pendTime / taskCB->schedStat.pendCount;
117         *pendTime = (averPendTime * OS_NS_PER_CYCLE) / OS_SYS_NS_PER_US;
118     }
119 
120     if (taskCB->schedStat.waitSchedCount > 0) {
121         UINT64 averSchedWait = taskCB->schedStat.waitSchedTime / taskCB->schedStat.waitSchedCount;
122         *schedWait = (averSchedWait * OS_NS_PER_CYCLE) / OS_SYS_NS_PER_US;
123     }
124 }
125 
OsShellShowSchedStatistics(VOID)126 UINT32 OsShellShowSchedStatistics(VOID)
127 {
128     UINT32 taskLinkNum[LOSCFG_KERNEL_CORE_NUM];
129     UINT32 intSave;
130     LosTaskCB task;
131 
132     SCHEDULER_LOCK(intSave);
133     for (UINT16 cpu = 0; cpu < LOSCFG_KERNEL_CORE_NUM; cpu++) {
134         SchedRunqueue *rq = OsSchedRunqueueByID(cpu);
135         taskLinkNum[cpu] = OsGetSortLinkNodeNum(&rq->timeoutQueue);
136     }
137     SCHEDULER_UNLOCK(intSave);
138 
139     for (UINT16 cpu = 0; cpu < LOSCFG_KERNEL_CORE_NUM; cpu++) {
140         PRINTK("cpu: %u Task SortMax: %u\n", cpu, taskLinkNum[cpu]);
141     }
142 
143     PRINTK("  Tid    AverRunTime(us)    SwitchCount  AverTimeSlice(us)    TimeSliceCount  AverReadyWait(us)  "
144            "AverPendTime(us)  TaskName \n");
145     for (UINT32 tid = 0; tid < g_taskMaxNum; tid++) {
146         LosTaskCB *taskCB = g_taskCBArray + tid;
147         SCHEDULER_LOCK(intSave);
148         if (OsTaskIsUnused(taskCB) || (taskCB->processID == OsGetIdleProcessID())) {
149             SCHEDULER_UNLOCK(intSave);
150             continue;
151         }
152 
153         (VOID)memcpy_s(&task, sizeof(LosTaskCB), taskCB, sizeof(LosTaskCB));
154         SCHEDULER_UNLOCK(intSave);
155 
156         UINT64 averRunTime = 0;
157         UINT64 averTimeSlice = 0;
158         UINT64 averPendTime = 0;
159         UINT64 averSchedWait = 0;
160 
161         SchedDataGet(&task, &averRunTime, &averTimeSlice, &averPendTime, &averSchedWait);
162 
163         PRINTK("%5u%19llu%15llu%19llu%18llu%19llu%18llu  %-32s\n", taskCB->taskID,
164                averRunTime, taskCB->schedStat.switchCount,
165                averTimeSlice, taskCB->schedStat.timeSliceCount - 1,
166                averSchedWait, averPendTime, taskCB->taskName);
167     }
168 
169     return LOS_OK;
170 }
171 #endif
172 
173