• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3  * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this list of
9  *    conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12  *    of conditions and the following disclaimer in the documentation and/or other materials
13  *    provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16  *    to endorse or promote products derived from this software without specific prior written
17  *    permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "los_cpup.h"
33 #include "securec.h"
34 #include "los_memory.h"
35 #include "los_debug.h"
36 #include "los_tick.h"
37 
38 #if (LOSCFG_BASE_CORE_CPUP == 1)
39 
40 /**
41  * @ingroup los_cpup
42  * CPU usage-type macro: used for tasks.
43  */
44 #define OS_THREAD_TYPE_TASK     0
45 
46 /**
47  * @ingroup los_cpup
48  * CPU usage-type macro: used for hardware interrupts.
49  */
50 #define OS_THREAD_TYPE_HWI      1
51 
52 #define OS_CPUP_RECORD_PERIOD   (g_sysClock)
53 
54 LITE_OS_SEC_BSS UINT16    g_cpupInitFlg = 0;
55 LITE_OS_SEC_BSS OsCpupCB  *g_cpup = NULL;
56 LITE_OS_SEC_BSS UINT64    g_lastRecordTime;
57 LITE_OS_SEC_BSS UINT16    g_hisPos; /* <current Sampling point of historyTime */
58 
59 /*****************************************************************************
60 Function   : OsCpupInit
61 Description: initialization of CPUP
62 Input      : None
63 Return     : LOS_OK or Error Information
64 *****************************************************************************/
OsCpupInit()65 LITE_OS_SEC_TEXT_INIT UINT32 OsCpupInit()
66 {
67     UINT32 size;
68 
69     size = g_taskMaxNum * sizeof(OsCpupCB);
70     g_cpup = (OsCpupCB *)LOS_MemAlloc(m_aucSysMem0, size);
71 
72     if (g_cpup == NULL) {
73         return LOS_ERRNO_CPUP_NO_MEMORY;
74     }
75 
76     // Ignore the return code when matching CSEC rule 6.6(3).
77     (VOID)memset_s(g_cpup, size, 0, size);
78     g_cpupInitFlg = 1;
79 
80     return LOS_OK;
81 }
82 
83 /*****************************************************************************
84 Function   : OsTskCycleStart
85 Description: start task to get cycles count in current task beginning
86 Input      : None
87 Return     : None
88 *****************************************************************************/
OsTskCycleStart(VOID)89 LITE_OS_SEC_TEXT_MINOR VOID OsTskCycleStart(VOID)
90 {
91     UINT32 taskID;
92 
93     if (g_cpupInitFlg == 0) {
94         return;
95     }
96 
97     taskID = g_losTask.newTask->taskID;
98     g_cpup[taskID].cpupID = taskID;
99     g_cpup[taskID].startTime = LOS_SysCycleGet();
100 
101     return;
102 }
103 /*****************************************************************************
104 Function   : OsTskCycleEnd
105 Description: quit task and get cycle count
106 Input      : None
107 Return     : None
108 *****************************************************************************/
OsTskCycleEnd(VOID)109 LITE_OS_SEC_TEXT_MINOR VOID OsTskCycleEnd(VOID)
110 {
111     UINT32 taskID;
112     UINT64 cpuCycle;
113 
114     if (g_cpupInitFlg == 0) {
115         return;
116     }
117 
118     taskID = g_losTask.runTask->taskID;
119 
120     if (g_cpup[taskID].startTime == 0) {
121         return;
122     }
123 
124     cpuCycle = LOS_SysCycleGet();
125 
126     if (cpuCycle < g_cpup[taskID].startTime) {
127         cpuCycle += g_cyclesPerTick;
128     }
129 
130     g_cpup[taskID].allTime += (cpuCycle - g_cpup[taskID].startTime);
131     g_cpup[taskID].startTime = 0;
132 
133     return;
134 }
135 /*****************************************************************************
136 Function   : OsTskCycleEndStart
137 Description: start task to get cycles count in current task ending
138 Input      : None
139 Return     : None
140 *****************************************************************************/
OsTskCycleEndStart(VOID)141 LITE_OS_SEC_TEXT_MINOR VOID OsTskCycleEndStart(VOID)
142 {
143     UINT32 taskID;
144     UINT64 cpuCycle;
145     UINT16 loopNum;
146 
147     if (g_cpupInitFlg == 0) {
148         return;
149     }
150 
151     taskID = g_losTask.runTask->taskID;
152     cpuCycle = LOS_SysCycleGet();
153 
154     if (g_cpup[taskID].startTime != 0) {
155         if (cpuCycle < g_cpup[taskID].startTime) {
156             cpuCycle += g_cyclesPerTick;
157         }
158 
159         g_cpup[taskID].allTime += (cpuCycle - g_cpup[taskID].startTime);
160         g_cpup[taskID].startTime = 0;
161     }
162 
163     taskID = g_losTask.newTask->taskID;
164     g_cpup[taskID].cpupID = taskID;
165     g_cpup[taskID].startTime = cpuCycle;
166 
167     if ((cpuCycle - g_lastRecordTime) > OS_CPUP_RECORD_PERIOD) {
168         g_lastRecordTime = cpuCycle;
169 
170         for (loopNum = 0; loopNum < g_taskMaxNum; loopNum++) {
171             g_cpup[loopNum].historyTime[g_hisPos] = g_cpup[loopNum].allTime;
172         }
173 
174         if (g_hisPos == (OS_CPUP_HISTORY_RECORD_NUM - 1)) {
175             g_hisPos = 0;
176         } else {
177             g_hisPos++;
178         }
179     }
180 
181     return;
182 }
183 
OsGetPrePos(UINT16 curPos)184 LITE_OS_SEC_TEXT_MINOR static inline UINT16 OsGetPrePos(UINT16 curPos)
185 {
186     return (curPos == 0) ? (OS_CPUP_HISTORY_RECORD_NUM - 1) : (curPos - 1);
187 }
188 
OsGetPositions(UINT16 mode,UINT16 * curPosAddr,UINT16 * prePosAddr)189 LITE_OS_SEC_TEXT_MINOR static VOID OsGetPositions(UINT16 mode, UINT16* curPosAddr, UINT16* prePosAddr)
190 {
191     UINT16 curPos;
192     UINT16 prePos = 0;
193 
194     curPos = g_hisPos;
195 
196     if (mode == CPUP_IN_1S) {
197         curPos = OsGetPrePos(curPos);
198         prePos = OsGetPrePos(curPos);
199     } else if (mode == CPUP_LESS_THAN_1S) {
200         curPos = OsGetPrePos(curPos);
201     }
202 
203     *curPosAddr = curPos;
204     *prePosAddr = prePos;
205 }
206 
207 /*****************************************************************************
208 Function   : LOS_SysCpuUsage
209 Description: get current CPU usage
210 Input      : None
211 Return     : cpupRet:current CPU usage
212 *****************************************************************************/
LOS_SysCpuUsage(VOID)213 LITE_OS_SEC_TEXT_MINOR UINT32 LOS_SysCpuUsage(VOID)
214 {
215     UINT64  cpuCycleAll = 0;
216     UINT32  cpupRet = 0;
217     UINT16  loopNum;
218     UINT32 intSave;
219 
220     if (g_cpupInitFlg == 0) {
221         return LOS_ERRNO_CPUP_NO_INIT;
222     }
223 
224     // get end time of current task
225     intSave = LOS_IntLock();
226     OsTskCycleEnd();
227 
228     for (loopNum = 0; loopNum < g_taskMaxNum; loopNum++) {
229         cpuCycleAll += g_cpup[loopNum].allTime;
230     }
231 
232     if (cpuCycleAll) {
233         cpupRet = LOS_CPUP_PRECISION -  (UINT32)((LOS_CPUP_PRECISION *
234             g_cpup[g_idleTaskID].allTime) / cpuCycleAll);
235     }
236 
237     OsTskCycleStart();
238     LOS_IntRestore(intSave);
239 
240     return cpupRet;
241 }
242 
243 /*****************************************************************************
244 Function   : LOS_HistorySysCpuUsage
245 Description: get CPU usage history
246 Input      : mode: mode,0 = usage in 10s,1 = usage in last 1s, else = less than 1s
247 Return     : cpupRet:CPU usage history
248 *****************************************************************************/
LOS_HistorySysCpuUsage(UINT16 mode)249 LITE_OS_SEC_TEXT_MINOR UINT32 LOS_HistorySysCpuUsage(UINT16 mode)
250 {
251     UINT64  cpuCycleAll = 0;
252     UINT64  idleCycleAll = 0;
253     UINT32  cpupRet = 0;
254     UINT16  loopNum;
255     UINT16  curPos;
256     UINT16  prePos = 0;
257     UINT32 intSave;
258 
259     if (g_cpupInitFlg == 0) {
260         return LOS_ERRNO_CPUP_NO_INIT;
261     }
262 
263     // get end time of current task
264     intSave = LOS_IntLock();
265     OsTskCycleEnd();
266 
267     OsGetPositions(mode, &curPos, &prePos);
268 
269     for (loopNum = 0; loopNum < g_taskMaxNum; loopNum++) {
270         if (mode == CPUP_IN_1S) {
271             cpuCycleAll += g_cpup[loopNum].historyTime[curPos] - g_cpup[loopNum].historyTime[prePos];
272         } else {
273             cpuCycleAll += g_cpup[loopNum].allTime - g_cpup[loopNum].historyTime[curPos];
274         }
275     }
276 
277     if (mode == CPUP_IN_1S) {
278         idleCycleAll += g_cpup[g_idleTaskID].historyTime[curPos] -
279                            g_cpup[g_idleTaskID].historyTime[prePos];
280     } else {
281         idleCycleAll += g_cpup[g_idleTaskID].allTime - g_cpup[g_idleTaskID].historyTime[curPos];
282     }
283 
284     if (cpuCycleAll) {
285         cpupRet = (LOS_CPUP_PRECISION -  (UINT32)((LOS_CPUP_PRECISION * idleCycleAll) / cpuCycleAll));
286     }
287 
288     OsTskCycleStart();
289     LOS_IntRestore(intSave);
290 
291     return cpupRet;
292 }
293 
294 /*****************************************************************************
295 Function   : LOS_TaskCpuUsage
296 Description: get CPU usage of certain task
297 Input      : taskID : task ID
298 Return     : cpupRet:CPU usage of certain task
299 *****************************************************************************/
LOS_TaskCpuUsage(UINT32 taskID)300 LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskCpuUsage(UINT32 taskID)
301 {
302     UINT64  cpuCycleAll = 0;
303     UINT16  loopNum;
304     UINT32 intSave;
305     UINT32  cpupRet = 0;
306 
307     if (g_cpupInitFlg == 0) {
308         return LOS_ERRNO_CPUP_NO_INIT;
309     }
310     if (OS_TSK_GET_INDEX(taskID) >= g_taskMaxNum) {
311         return LOS_ERRNO_CPUP_TSK_ID_INVALID;
312     }
313     if (g_cpup[taskID].cpupID != taskID) {
314         return LOS_ERRNO_CPUP_THREAD_NO_CREATED;
315     }
316     if ((g_cpup[taskID].status & OS_TASK_STATUS_UNUSED) || (g_cpup[taskID].status == 0)) {
317         return LOS_ERRNO_CPUP_THREAD_NO_CREATED;
318     }
319     intSave = LOS_IntLock();
320     OsTskCycleEnd();
321 
322     /* get total Cycle */
323     for (loopNum = 0; loopNum < g_taskMaxNum; loopNum++) {
324         if ((g_cpup[loopNum].status & OS_TASK_STATUS_UNUSED) || (g_cpup[loopNum].status == 0)) {
325             continue;
326         }
327         cpuCycleAll += g_cpup[loopNum].allTime;
328     }
329 
330     if (cpuCycleAll) {
331         cpupRet = (UINT32)((LOS_CPUP_PRECISION * g_cpup[taskID].allTime) / cpuCycleAll);
332     }
333 
334     OsTskCycleStart();
335     LOS_IntRestore(intSave);
336 
337     return cpupRet;
338 }
339 
340 /*****************************************************************************
341 Function   : LOS_HistoryTaskCpuUsage
342 Description: get CPU usage history of certain task
343 Input      : taskID : task ID
344            : mode: mode,0 = usage in 10s,1 = usage in last 1s, else = less than 1s
345 Return     : cpupRet:CPU usage history of task
346 *****************************************************************************/
LOS_HistoryTaskCpuUsage(UINT32 taskID,UINT16 mode)347 LITE_OS_SEC_TEXT_MINOR UINT32 LOS_HistoryTaskCpuUsage(UINT32 taskID, UINT16 mode)
348 {
349     UINT64  cpuCycleAll = 0;
350     UINT64  cpuCycleCurTsk = 0;
351     UINT16  loopNum, curPos;
352     UINT16  prePos = 0;
353     UINT32 intSave;
354     UINT32  cpupRet = 0;
355 
356     if (g_cpupInitFlg == 0) {
357         return LOS_ERRNO_CPUP_NO_INIT;
358     }
359     if (OS_TSK_GET_INDEX(taskID) >= g_taskMaxNum) {
360         return LOS_ERRNO_CPUP_TSK_ID_INVALID;
361     }
362     if (g_cpup[taskID].cpupID != taskID) {
363         return LOS_ERRNO_CPUP_THREAD_NO_CREATED;
364     }
365     if ((g_cpup[taskID].status & OS_TASK_STATUS_UNUSED) || (g_cpup[taskID].status == 0)) {
366         return LOS_ERRNO_CPUP_THREAD_NO_CREATED;
367     }
368     intSave = LOS_IntLock();
369     OsTskCycleEnd();
370 
371     OsGetPositions(mode, &curPos, &prePos);
372 
373     /* get total Cycle in history */
374     for (loopNum = 0; loopNum < g_taskMaxNum; loopNum++) {
375         if ((g_cpup[loopNum].status & OS_TASK_STATUS_UNUSED) || (g_cpup[loopNum].status == 0)) {
376             continue;
377         }
378 
379         if (mode == CPUP_IN_1S) {
380             cpuCycleAll += g_cpup[loopNum].historyTime[curPos] - g_cpup[loopNum].historyTime[prePos];
381         } else {
382             cpuCycleAll += g_cpup[loopNum].allTime - g_cpup[loopNum].historyTime[curPos];
383         }
384     }
385 
386     if (mode == CPUP_IN_1S) {
387         cpuCycleCurTsk += g_cpup[taskID].historyTime[curPos] - g_cpup[taskID].historyTime[prePos];
388     } else {
389         cpuCycleCurTsk += g_cpup[taskID].allTime - g_cpup[taskID].historyTime[curPos];
390     }
391     if (cpuCycleAll) {
392         cpupRet = (UINT32)((LOS_CPUP_PRECISION * cpuCycleCurTsk) / cpuCycleAll);
393     }
394 
395     OsTskCycleStart();
396     LOS_IntRestore(intSave);
397 
398     return cpupRet;
399 }
400 
LOS_AllTaskCpuUsage(CPUP_INFO_S * cpupInfo,UINT16 mode)401 LITE_OS_SEC_TEXT_MINOR UINT32 LOS_AllTaskCpuUsage(CPUP_INFO_S *cpupInfo, UINT16 mode)
402 {
403     UINT16  loopNum;
404     UINT16  curPos;
405     UINT16  prePos = 0;
406     UINT32 intSave;
407     UINT64  cpuCycleAll = 0;
408     UINT64  cpuCycleCurTsk = 0;
409 
410     if (g_cpupInitFlg == 0) {
411         return  LOS_ERRNO_CPUP_NO_INIT;
412     }
413 
414     if (cpupInfo == NULL) {
415         return LOS_ERRNO_CPUP_TASK_PTR_NULL;
416     }
417 
418     intSave = LOS_IntLock();
419     OsTskCycleEnd();
420 
421     OsGetPositions(mode, &curPos, &prePos);
422 
423     for (loopNum = 0; loopNum < g_taskMaxNum; loopNum++) {
424         if ((g_cpup[loopNum].status & OS_TASK_STATUS_UNUSED) ||
425             (g_cpup[loopNum].status == 0)) {
426             continue;
427         }
428 
429         if (mode == CPUP_IN_1S) {
430             cpuCycleAll += g_cpup[loopNum].historyTime[curPos] - g_cpup[loopNum].historyTime[prePos];
431         } else {
432             cpuCycleAll += g_cpup[loopNum].allTime - g_cpup[loopNum].historyTime[curPos];
433         }
434     }
435 
436     for (loopNum = 0; loopNum < g_taskMaxNum; loopNum++) {
437         if ((g_cpup[loopNum].status & OS_TASK_STATUS_UNUSED) ||
438             (g_cpup[loopNum].status == 0)) {
439             continue;
440         }
441 
442         if (mode == CPUP_IN_1S) {
443             cpuCycleCurTsk += g_cpup[loopNum].historyTime[curPos] - g_cpup[loopNum].historyTime[prePos];
444         } else {
445             cpuCycleCurTsk += g_cpup[loopNum].allTime - g_cpup[loopNum].historyTime[curPos];
446         }
447         cpupInfo[loopNum].usStatus = g_cpup[loopNum].status;
448         if (cpuCycleAll) {
449             cpupInfo[loopNum].uwUsage = (UINT32)((LOS_CPUP_PRECISION * cpuCycleCurTsk) / cpuCycleAll);
450         }
451 
452         cpuCycleCurTsk = 0;
453     }
454 
455     OsTskCycleStart();
456     LOS_IntRestore(intSave);
457 
458     return LOS_OK;
459 }
460 
461 /*****************************************************************************
462 Function   : LOS_CpupUsageMonitor
463 Description: Get CPU usage history of certain task.
464 Input      : type: cpup type, SYS_CPU_USAGE and TASK_CPU_USAGE
465            : taskID: task ID, Only in SYS_CPU_USAGE type, taskID is invalid
466            : mode: mode, CPUP_IN_10S = usage in 10s, CPUP_IN_1S = usage in last 1s, CPUP_LESS_THAN_1S = less than 1s
467 Return     : LOS_OK on success, or OS_ERROR on failure
468 *****************************************************************************/
LOS_CpupUsageMonitor(CPUP_TYPE_E type,CPUP_MODE_E mode,UINT32 taskID)469 LITE_OS_SEC_TEXT_MINOR UINT32 LOS_CpupUsageMonitor(CPUP_TYPE_E type, CPUP_MODE_E mode, UINT32 taskID)
470 {
471     UINT32 ret;
472     LosTaskCB *taskCB = NULL;
473 
474     switch (type) {
475         case SYS_CPU_USAGE:
476             if (mode == CPUP_IN_10S) {
477                 PRINTK("\nSysCpuUsage in 10s: ");
478             } else if (mode == CPUP_IN_1S) {
479                 PRINTK("\nSysCpuUsage in 1s: ");
480             } else {
481                 PRINTK("\nSysCpuUsage in <1s: ");
482             }
483             ret = LOS_HistorySysCpuUsage(mode);
484             PRINTK("%d.%d", ret / LOS_CPUP_PRECISION_MULT, ret % LOS_CPUP_PRECISION_MULT);
485             break;
486 
487         case TASK_CPU_USAGE:
488             if (taskID > LOSCFG_BASE_CORE_TSK_LIMIT) {
489                 PRINT_ERR("\nThe taskid is invalid.\n");
490                 return OS_ERROR;
491             }
492             taskCB = OS_TCB_FROM_TID(taskID);
493             if ((taskCB->taskStatus & OS_TASK_STATUS_UNUSED)) {
494                 PRINT_ERR("\nThe taskid is invalid.\n");
495                 return OS_ERROR;
496             }
497             if (mode == CPUP_IN_10S) {
498                 PRINTK("\nCPUusage of taskID %d in 10s: ", taskID);
499             } else if (mode == CPUP_IN_1S) {
500                 PRINTK("\nCPUusage of taskID %d in 1s: ", taskID);
501             } else {
502                 PRINTK("\nCPUusage of taskID %d in <1s: ", taskID);
503             }
504             ret = LOS_HistoryTaskCpuUsage(taskID, mode);
505             PRINTK("%u.%u", ret / LOS_CPUP_PRECISION_MULT, ret % LOS_CPUP_PRECISION_MULT);
506             break;
507 
508         default:
509             PRINT_ERR("\nThe type is invalid.\n");
510             return OS_ERROR;
511     }
512 
513     return LOS_OK;
514 }
515 
516 #endif /* LOSCFG_BASE_CORE_CPUP */
517