• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved.
3  *
4  * UniProton is licensed under Mulan PSL v2.
5  * You can use this software according to the terms and conditions of the Mulan PSL v2.
6  * You may obtain a copy of Mulan PSL v2 at:
7  *          http://license.coscl.org.cn/MulanPSL2
8  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
9  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
10  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
11  * See the Mulan PSL v2 for more details.
12  * Create: 2009-12-22
13  * Description: 线程级CPU占用率模块的C文件
14  */
15 #include "prt_cpup_thread_internal.h"
16 
17 /*
18  * 描述:任务切入,中断结束时,统计任务的startTime
19  */
OsNowTskCycleStart(void)20 OS_SEC_L2_TEXT void OsNowTskCycleStart(void)
21 {
22     uintptr_t intSave;
23 
24     intSave = OsIntLock();
25 
26     /* 处理硬中断、Tick退出钩子时判断是否需要统计CPUP */
27     if (CPUP_FLAG == OS_CPUP_EXIT_FLAG) {
28         OS_TASK_CYCLE_START(RUNNING_TASK->taskPid, OsCurCycleGet64());
29     }
30     CPUP_FLAG--;
31 
32     OsIntRestore(intSave);
33 }
34 
35 /*
36  * 描述:任务切出,中断开始时,统计任务的allTime
37  */
OsNowTskCycleEnd(void)38 OS_SEC_L2_TEXT void OsNowTskCycleEnd(void)
39 {
40     uintptr_t intSave;
41 
42     intSave = OsIntLock();
43 
44     /* 处理硬中断、Tick进入钩子时判断是否需要统计CPUP */
45     if (CPUP_FLAG == OS_CPUP_ENTRY_FLAG) {
46         OS_TASK_CYCLE_END(RUNNING_TASK->taskPid, OsCurCycleGet64());
47     }
48     CPUP_FLAG++;
49 
50     OsIntRestore(intSave);
51 }
52 
53 /*
54  * 描述:第一次任务切换时候CPUP设初始值
55  */
OsCpupFirstSwitch(void)56 OS_SEC_L2_TEXT void OsCpupFirstSwitch(void)
57 {
58     g_cpuWinStart = OsCurCycleGet64();
59     OS_TASK_CYCLE_START(g_highestTask->taskPid, g_cpuWinStart);
60 }
61 
62 /*
63  * 描述:任务结束和开始,对任务的CPUP计时
64  * 备注:lastTaskId 结束的任务ID;nextTaskId 开始的任务ID;curCycle  结束和开始的Cycle
65  */
OsCpupStartEnd(U32 lastTaskId,U32 nextTaskId,U64 curCycle)66 OS_SEC_L2_TEXT void OsCpupStartEnd(U32 lastTaskId, U32 nextTaskId, U64 curCycle)
67 {
68     /* 切出任务 */
69     OS_TASK_CYCLE_END(lastTaskId, curCycle);
70 
71     /* 切入任务 */
72     OS_TASK_CYCLE_START(nextTaskId, curCycle);
73 }
74 
75 /*
76  * 描述:任务切换时候CPUP设初始值
77  */
OsCpupTskSwitch(U32 lastTaskId,U32 nextTaskId)78 OS_SEC_L2_TEXT void OsCpupTskSwitch(U32 lastTaskId, U32 nextTaskId)
79 {
80     uintptr_t intSave;
81 
82     intSave = OsIntLock();
83     /* CPUP统计 */
84     OsCpupStartEnd(lastTaskId, nextTaskId, OsCurCycleGet64());
85 
86     OsIntRestore(intSave);
87 }
88 /*
89  * 描述:获取输入线程个数的cpup
90  */
OsCpupTask(U32 intNum,struct CpupThread * cpup)91 OS_SEC_L2_TEXT U32 OsCpupTask(U32 intNum, struct CpupThread *cpup)
92 {
93     U32 index;
94     U32 maxNum = 0;
95     cpup[maxNum].id = OS_CPUP_INT_ID;
96     cpup[maxNum].usage = OsCpupIntGet();
97     maxNum++;
98 
99     for (index = 0; index < (OS_MAX_TCB_NUM - 1); index++) {
100         if (intNum == maxNum) {
101             break;
102         }
103 
104         /* 判断该任务是否被创建 */
105         if (g_tskCbArray[index].taskStatus == OS_TSK_UNUSED) {
106             continue;
107         }
108 
109         cpup[maxNum].id = g_tskCbArray[index].taskPid;
110         cpup[maxNum].usage = g_cpup[index].usage;
111 
112         maxNum++;
113     }
114     return maxNum;
115 }
116 
OsCpupParaCheck(U32 intNum,struct CpupThread * cpup,const U32 * outNum)117 OS_SEC_ALW_INLINE INLINE U32 OsCpupParaCheck(U32 intNum, struct CpupThread *cpup, const U32 *outNum)
118 {
119     if (cpup == NULL || outNum == NULL) {
120         return OS_ERRNO_CPUP_PTR_NULL;
121     }
122 
123     if (intNum == 0) {
124         return OS_ERRNO_CPUP_THREAD_INNUM_INVALID;
125     }
126 
127     return OS_OK;
128 }
129 
130 /*
131  * 描述:获取所有任务线程的运行时间
132  */
OsCpupAllTaskTimeGet(void)133 OS_SEC_L2_TEXT U64 OsCpupAllTaskTimeGet(void)
134 {
135     U32 index;
136     U64 allTime = 0;
137 
138     for (index = 0; index < (OS_MAX_TCB_NUM - 1); index++) {
139         allTime += g_cpup[index].allTime;
140     }
141 
142     return (allTime + g_cpuTimeDelTask);
143 }
144 
145 /*
146  * 描述:清空所有任务运行时间和CPU占用率大小
147  */
OsCpupTimeClear(void)148 OS_SEC_L2_TEXT void OsCpupTimeClear(void)
149 {
150     U32 index;
151 
152     for (index = 0; index < (OS_MAX_TCB_NUM - 1); index++) {
153         g_cpup[index].allTime = 0;
154     }
155 
156     g_cpuTimeDelTask = 0;
157 }
158 /*
159  * 描述:清空所有任务运行时间和CPU占用率大小
160  */
OsCpupTickCal(void)161 OS_SEC_L2_TEXT void OsCpupTickCal(void)
162 {
163     U32 index;
164 
165     for (index = 0; index < (OS_MAX_TCB_NUM - 1); index++) {
166         g_cpup[index].usage = (U16)DIV64(g_cpup[index].allTime * CPUP_USE_RATE, g_baseValue);
167         if (g_cpup[index].usage > CPUP_USE_RATE) {
168             g_cpup[index].usage = CPUP_USE_RATE;
169         }
170     }
171 
172     OsMcCpupSet(OsGetHwThreadId(), (U32)(CPUP_USE_RATE - g_cpup[TSK_GET_INDEX(IDLE_TASK_ID)].usage));
173 
174     g_cpupDelTask = (U16)DIV64(g_cpuTimeDelTask * CPUP_USE_RATE, g_baseValue);
175 }
176 
177 /*
178  * 描述:获取中断线程的占用率接口
179  */
OsCpupIntGet(void)180 OS_SEC_L2_TEXT U16 OsCpupIntGet(void)
181 {
182     U32 index;
183     U16 usage = 0;
184 
185     for (index = 0; index < (OS_MAX_TCB_NUM - 1); index++) {
186         usage += g_cpup[index].usage;
187     }
188 
189     usage += g_cpupDelTask;
190 
191     if (usage >= CPUP_USE_RATE) {
192         usage = CPUP_USE_RATE;
193     }
194 
195     return (U16)(CPUP_USE_RATE - usage);
196 }
197 
198 /*
199  * 描述:获取当前线程级cpu占用率接口
200  */
OsCpupThreadNow(void)201 OS_SEC_L2_TEXT U32 OsCpupThreadNow(void)
202 {
203     U64 cpuCycleAll;
204     uintptr_t intSave;
205     U32 cpup = 0;
206     U64 curCycle;
207 
208     if ((UNI_FLAG & OS_FLG_BGD_ACTIVE) == 0) {
209         OS_REPORT_ERROR(OS_ERRNO_CPUP_OS_NOT_STARTED);
210         return (U32)OS_INVALID;
211     }
212 
213     intSave = OsIntLock();
214 
215     if (g_ticksPerSample != 0) {
216         cpup = (U32)(CPUP_USE_RATE - g_cpup[TSK_GET_INDEX(IDLE_TASK_ID)].usage);
217 
218         OsIntRestore(intSave);
219         return cpup;
220     }
221 
222     /* 统计当前系统运行总时间 */
223     curCycle = OsCurCycleGet64();
224 
225     if (OS_INT_INACTIVE) {
226         OsCpupStartEnd(RUNNING_TASK->taskPid, RUNNING_TASK->taskPid, curCycle);
227     }
228 
229     cpuCycleAll = OsCpupGetWinCycles(curCycle);
230     g_cpuWinStart = curCycle;
231 
232     cpup = (U32)(CPUP_USE_RATE - DIV64(CPUP_USE_RATE * g_cpup[TSK_GET_INDEX(IDLE_TASK_ID)].allTime, cpuCycleAll));
233     OsMcCpupSet(OsGetHwThreadId(), cpup);
234 
235     OsCpupTimeClear();
236 
237     OsIntRestore(intSave);
238 
239     return cpup;
240 }
241 
242 /*
243  * 描述:获取所有线程的占用率接口
244  */
PRT_CpupThread(U32 inNum,struct CpupThread * cpup,U32 * outNum)245 OS_SEC_L2_TEXT U32 PRT_CpupThread(U32 inNum, struct CpupThread *cpup, U32 *outNum)
246 {
247     U32 index;
248     U32 ret;
249     uintptr_t intSave;
250     U32 maxNum = 1; // 默认中断占用一个
251 
252     U64 cpuCycleAll;
253     U64 allTime;
254     U64 curCycle;
255 
256     ret = OsCpupPreCheck();
257     if (ret != OS_OK) {
258         return ret;
259     }
260 
261     ret = OsCpupParaCheck(inNum, cpup, outNum);
262     if (ret != OS_OK) {
263         return ret;
264     }
265 
266     /* 获取当前采样周期内,所有线程运行的总时间 */
267     intSave = OsIntLock();
268 
269     if (g_ticksPerSample != 0) {
270         maxNum = OsCpupTask(inNum, cpup);
271         OsIntRestore(intSave);
272         *outNum = maxNum;
273 
274         return OS_OK;
275     }
276 
277     curCycle = OsCurCycleGet64();
278 
279     if (OS_INT_INACTIVE) {
280         OsCpupStartEnd(RUNNING_TASK->taskPid, RUNNING_TASK->taskPid, curCycle);
281     }
282     /* 统计当前系统运行总时间 */
283     cpuCycleAll = OsCpupGetWinCycles(curCycle);
284     g_cpuWinStart = curCycle;
285 
286     /*
287      * 配置g_cpup[].iD线程ID
288      */
289     cpup[0].id = OS_CPUP_INT_ID;
290     cpup[0].usage = (U16)DIV64(CPUP_USE_RATE * (cpuCycleAll - OsCpupAllTaskTimeGet()), cpuCycleAll);
291 
292     for (index = 0; index < (OS_MAX_TCB_NUM - 1) && maxNum < inNum; index++) {
293         /* 判断该任务是否被创建 */
294         if (g_tskCbArray[index].taskStatus == OS_TSK_UNUSED) {
295             continue;
296         }
297 
298         allTime = g_cpup[index].allTime;
299 
300         cpup[maxNum].id = g_tskCbArray[index].taskPid;
301         cpup[maxNum].usage = (U16)DIV64(CPUP_USE_RATE * allTime, cpuCycleAll);
302 
303         maxNum++;
304     }
305 
306     OsMcCpupSet(OsGetHwThreadId(),
307                 (U32)DIV64(CPUP_USE_RATE * (cpuCycleAll - g_cpup[TSK_GET_INDEX(IDLE_TASK_ID)].allTime), cpuCycleAll));
308 
309     OsCpupTimeClear();
310 
311     OsIntRestore(intSave);
312     *outNum = maxNum;
313 
314     return OS_OK;
315 }
316