摘要:CPUP(Central Processing Unit Percentage,CPU佔用率)分爲系統CPU佔用率和任務CPU佔用率。用戶通過系統級的CPU佔用率,判斷當前系統負載是否超出設計規格。通過系統中各個任務的CPU佔用情況,判斷各個任務的CPU佔用率是否符合設計的預期。
本文分享自華爲雲社區《鴻蒙輕內核M核源碼分析系列十五 CPU使用率CPUP (1)》,作者:zhushy。
CPUP(Central Processing Unit Percentage,CPU佔用率)分爲系統CPU佔用率和任務CPU佔用率。用戶通過系統級的CPU佔用率,判斷當前系統負載是否超出設計規格。通過系統中各個任務的CPU佔用情況,判斷各個任務的CPU佔用率是否符合設計的預期。
系統CPU佔用率是指週期時間內系統的CPU佔用率,用於表示系統一段時間內的閒忙程度,也表示CPU的負載情況。系統CPU佔用率的有效表示範圍爲0~100,其精度(可通過配置調整)爲百分比。100表示系統滿負荷運轉。
任務CPU佔用率指單個任務的CPU佔用率,用於表示單個任務在一段時間內的閒忙程度。任務CPU佔用率的有效表示範圍爲0~100,其精度(可通過配置調整)爲百分比。100表示在一段時間內系統一直在運行該任務。
本文通過分析鴻蒙輕內核CPUP擴展模塊的源碼。本文中所涉及的源碼,以OpenHarmony LiteOS-M內核爲例, 均可以在開源站點https://gitee.com/openharmony/kernel_liteos_m 獲取。
CPUP模塊用任務級記錄的方式,在任務切換時,記錄任務啓動時間,任務切出或者退出時間,每次當任務退出時,系統會累加整個任務的佔用時間。接下來,我們看下CPUP模塊支持的常見操作的源代碼。
1、CPUP結構體定義和常用宏定義
1.1 CPUP結構體定義
在文件components\cpup\los_cpup.h定義的CPUP控制塊結構體爲OsCpupCB,結構體源代碼如下,allTime記錄該任務自系統啓動以來運行的cycle數,startTime記錄任務開始運行的時間,historyTime[]歷史運行時間數組的10個元素記錄最近10秒中每一秒中每個任務自系統啓動以來運行的cycle數,其他結構體成員的解釋見註釋部分。
typedef struct {
UINT32 cpupID; /**< 任務編號 */
UINT16 status; /**< 任務狀態 */
UINT64 allTime; /**< 總共運行的時間 */
UINT64 startTime; /**< 任務開始時間 */
UINT64 historyTime[OS_CPUP_HISTORY_RECORD_NUM]; /**< 歷史運行時間數組,其中OS_CPUP_HISTORY_RECORD_NUM爲10 */
} OsCpupCB;
另外,還定義了一個結構體CPUP_INFO_S,如下:
typedef struct tagCpupInfo {
UINT16 usStatus; /**< 保存當前運行任務狀態 */
UINT32 uwUsage; /**< 使用情況,值範圍爲 [0,1000]. */
} CPUP_INFO_S;
1.2 CPUP枚舉定義
CPUP頭文件components\cpup\los_cpup.h中還提供了相關的枚舉,CPUP佔用率類型CPUP_TYPE_E,及CPUP統計時間間隔模式CPUP_MODE_E。
typedef enum {
SYS_CPU_USAGE = 0, /* 系統CPUP */
TASK_CPU_USAGE, /* 任務CPUP */
} CPUP_TYPE_E;
typedef enum {
CPUP_IN_10S = 0, /* CPUP統計週期10s */
CPUP_IN_1S, /* CPUP統計週期1s */
CPUP_LESS_THAN_1S, /* CPUP統計週期<1s */
} CPUP_MODE_E;
2、CPUP初始化
CPUP默認關閉,用戶可以通過宏LOSCFG_BASE_CORE_CPUP進行開啓。開啓CPUP的情況下,在系統啓動時,在kernel\src\los_init.c中調用OsCpupInit()進行CPUP模塊初始化。下面,我們分析下CPUP初始化的代碼。
⑴處計算CPUP結構體池需要的內存大小,然後爲CPUP申請內存,如果申請失敗,則返回錯誤。⑵處初始化成功後,設置初始化標記g_cpupInitFlg。
LITE_OS_SEC_TEXT_INIT UINT32 OsCpupInit()
{
UINT32 size;
size = g_taskMaxNum * sizeof(OsCpupCB);
⑴ g_cpup = (OsCpupCB *)LOS_MemAlloc(m_aucSysMem0, size);
if (g_cpup == NULL) {
return LOS_ERRNO_CPUP_NO_MEMORY;
}
(VOID)memset_s(g_cpup, size, 0, size);
⑵ g_cpupInitFlg = 1;
return LOS_OK;
}
3、CPUP常用操作
3.1 CPUP內部接口
我們先分析下內部接口,這些接口會被LOS_開頭的外部接口調用。
3.1.1 OsTskCycleStart記錄任務開始時間
CPUP模塊對外接口執行後期會調用該內部接口,設置下一個任務的開始運行時間。
⑴處先判斷CPUP是否已經初始化,如果沒有初始化過,退出該函數的執行。⑵處獲取新任務的任務編號。⑶處設置該任務對應的CPUP結構體的任務編號和開始時間。
LITE_OS_SEC_TEXT_MINOR VOID OsTskCycleStart(VOID)
{
UINT32 taskID;
⑴ if (g_cpupInitFlg == 0) {
return;
}
⑵ taskID = g_losTask.newTask->taskID;
⑶ g_cpup[taskID].cpupID = taskID;
g_cpup[taskID].startTime = LOS_SysCycleGet();
return;
}
3.1.2 OsTskCycleEnd記錄任務結束時間
CPUP模塊對外接口執行前期會調用該內部接口,獲取當前任務的結束時間,並統計當前任務的運行總時間。
⑴處先判斷CPUP是否已經初始化,如果沒有初始化過,退出該函數的執行。⑵處獲取當前任務的任務編號。⑶處如果該任務的開始時間爲0,退出函數執行。⑷處獲取系統的當前cycle數。⑸如果獲取的小於任務CPUP開始時間,則把獲取的cycle數加上每個tick的cycle數。⑹處計算當前任務的運行的總時間,然後把開始時間置0。
LITE_OS_SEC_TEXT_MINOR VOID OsTskCycleEnd(VOID)
{
UINT32 taskID;
UINT64 cpuCycle;
⑴ if (g_cpupInitFlg == 0) {
return;
}
⑵ taskID = g_losTask.runTask->taskID;
⑶ if (g_cpup[taskID].startTime == 0) {
return;
}
⑷ cpuCycle = LOS_SysCycleGet();
⑸ if (cpuCycle < g_cpup[taskID].startTime) {
cpuCycle += g_cyclesPerTick;
}
⑹ g_cpup[taskID].allTime += (cpuCycle - g_cpup[taskID].startTime);
g_cpup[taskID].startTime = 0;
return;
}
3.1.3 OsTskCycleEndStart任務切換時更新任務歷史運行時間
該函數在任務調度切換時會被執行,計算當前運行任務的運行總時間,記錄新任務的開始時間,並更新所有任務的歷史運行時間。函數的示意圖如下:
⑴處先判斷CPUP是否已經初始化,如果沒有初始化過,退出該函數的執行。⑵處獲取當前任務的任務編號,然後獲取系統的當前cycle數。⑶處如果當前任務的開始時間不爲0,則計算當前任務的運行的總時間,然後把開始時間置0。
⑷處獲取新任務的任務編號,⑸處設置該任務對應的CPUP結構體的任務編號和開始時間。⑹處如果記錄間隔大於系統時鐘(即每秒的cycle數),更新上次記錄時間。這意味着每個任務的historyTime[]數組中的每個元素表示1s多的週期內該任務的運行cycle數量,並不是非常精確的。然後執行⑺,記錄每一個任務對應的CPUP的歷史運行時間。⑻處更新歷史運行時間數組的當前索引值。
LITE_OS_SEC_TEXT_MINOR VOID OsTskCycleEndStart(VOID)
{
UINT32 taskID;
UINT64 cpuCycle;
UINT16 loopNum;
⑴ if (g_cpupInitFlg == 0) {
return;
}
⑵ taskID = g_losTask.runTask->taskID;
cpuCycle = LOS_SysCycleGet();
⑶ if (g_cpup[taskID].startTime != 0) {
if (cpuCycle < g_cpup[taskID].startTime) {
cpuCycle += g_cyclesPerTick;
}
g_cpup[taskID].allTime += (cpuCycle - g_cpup[taskID].startTime);
g_cpup[taskID].startTime = 0;
}
⑷ taskID = g_losTask.newTask->taskID;
⑸ g_cpup[taskID].cpupID = taskID;
g_cpup[taskID].startTime = cpuCycle;
⑹ if ((cpuCycle - g_lastRecordTime) > OS_CPUP_RECORD_PERIOD) {
g_lastRecordTime = cpuCycle;
for (loopNum = 0; loopNum < g_taskMaxNum; loopNum++) {
⑺ g_cpup[loopNum].historyTime[g_hisPos] = g_cpup[loopNum].allTime;
}
⑻ if (g_hisPos == (OS_CPUP_HISTORY_RECORD_NUM - 1)) {
g_hisPos = 0;
} else {
g_hisPos++;
}
}
return;
}
3.1.4 OsGetPrePos獲取歷史運行時間數組上一索引位置
代碼比較簡單,如果傳入參數curPos爲0,則返回數組的最後一個索引位置OS_CPUP_HISTORY_RECORD_NUM - 1。否則返回減1返回。
LITE_OS_SEC_TEXT_MINOR static inline UINT16 OsGetPrePos(UINT16 curPos)
{
return (curPos == 0) ? (OS_CPUP_HISTORY_RECORD_NUM - 1) : (curPos - 1);
}
3.1.5 OsGetPositions獲取歷史運行時間數組的當前及上一索引位置
根據CPUP統計時間間隔模式,獲取歷史運行時間數組的當前及上一索引位置。
⑴處獲取歷史運行時間數組的當前索引位置,⑵如果時間間隔模式爲1秒,當前索引curPos位置爲g_hisPos的上一索引位置,上一索引位置prePos需要繼續上前一位。⑶如果時間間隔模式小於1秒,當前索引curPos位置爲g_hisPos的上一索引位置,上一索引位置prePos爲0。如果時間間隔模式是10秒,當前索引curPos位置就等於g_hisPos,上一索引位置prePos爲0。⑷處設置傳出參數。
LITE_OS_SEC_TEXT_MINOR static VOID OsGetPositions(UINT16 mode, UINT16* curPosAddr, UINT16* prePosAddr)
{
UINT16 curPos;
UINT16 prePos = 0;
⑴ curPos = g_hisPos;
⑵ if (mode == CPUP_IN_1S) {
curPos = OsGetPrePos(curPos);
prePos = OsGetPrePos(curPos);
⑶ } else if (mode == CPUP_LESS_THAN_1S) {
curPos = OsGetPrePos(curPos);
}
⑷ *curPosAddr = curPos;
*prePosAddr = prePos;
}
3.2 CPUP對外接口
我們先分析下外部接口,接口說明如下:
3.2.1 LOS_SysCpuUsage
該函數會統計當前系統CPU佔用率,返回值基於千分率計算,取值範圍爲[0,1000]。函數的示意圖如下:
⑴處先判斷CPUP是否已經初始化,如果沒有初始化過,返回錯誤碼。⑵處調用函數OsTskCycleEnd()獲取當前任務的結束時間,並計算出運行總時間。⑶處統計所有任務的運行總時間,如果總時間不爲0,執行⑷計算出系統的任務CPU佔用率。⑸處調用函數OsTskCycleStart()設置新任務的CPUP統計的開始時間。
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_SysCpuUsage(VOID)
{
UINT64 cpuCycleAll = 0;
UINT32 cpupRet = 0;
UINT16 loopNum;
UINT32 intSave;
⑴ if (g_cpupInitFlg == 0) {
return LOS_ERRNO_CPUP_NO_INIT;
}
intSave = LOS_IntLock();
⑵ OsTskCycleEnd();
⑶ for (loopNum = 0; loopNum < g_taskMaxNum; loopNum++) {
cpuCycleAll += g_cpup[loopNum].allTime;
}
⑷ if (cpuCycleAll) {
cpupRet = LOS_CPUP_PRECISION - (UINT32)((LOS_CPUP_PRECISION *
g_cpup[g_idleTaskID].allTime) / cpuCycleAll);
}
⑸ OsTskCycleStart();
LOS_IntRestore(intSave);
return cpupRet;
}
3.2.2 LOS_HistorySysCpuUsage
該函數獲取系統歷史CPU佔用率,對於歷史CPU佔用率,需要傳入時間間隔模式參數,支持10秒、1秒、小於1秒三種。
⑴處先判斷CPUP是否已經初始化,如果沒有初始化過,返回錯誤碼。⑵處調用函數OsTskCycleEnd()獲取當前任務的結束時間,並計算出運行總時間。⑶處調用函數OsGetPositions()計算出歷史運行時間數組索引位置。⑷處計算出各個任務的週期內運行總時間,如果時間間隔模式爲1秒,取值兩個歷史運行時間之差,即爲1秒內任務的運行時間數。對於時間間隔模式爲10秒,historyTime[curPos]表示10秒前的自系統啓動以來的任務運行的時間數,計算出來的差值即爲10秒內任務的運行時間數。對於時間間隔模式爲小於1秒,historyTime[curPos]表示上一秒前的自系統啓動以來的任務運行的時間數,計算出來的差值即爲小於1秒內任務的運行時間數。⑸處計算空閒任務週期內運行總時間。⑹處如果總時間不爲0,計算出系統的任務歷史CPU佔用率。最後,調用函數OsTskCycleStart()設置新任務的CPUP統計的開始時間。可以參考示意圖進行理解:
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_HistorySysCpuUsage(UINT16 mode)
{
UINT64 cpuCycleAll = 0;
UINT64 idleCycleAll = 0;
UINT32 cpupRet = 0;
UINT16 loopNum;
UINT16 curPos;
UINT16 prePos = 0;
UINT32 intSave;
⑴ if (g_cpupInitFlg == 0) {
return LOS_ERRNO_CPUP_NO_INIT;
}
// get end time of current task
intSave = LOS_IntLock();
⑵ OsTskCycleEnd();
⑶ OsGetPositions(mode, &curPos, &prePos);
for (loopNum = 0; loopNum < g_taskMaxNum; loopNum++) {
⑷ if (mode == CPUP_IN_1S) {
cpuCycleAll += g_cpup[loopNum].historyTime[curPos] - g_cpup[loopNum].historyTime[prePos];
} else {
cpuCycleAll += g_cpup[loopNum].allTime - g_cpup[loopNum].historyTime[curPos];
}
}
⑸ if (mode == CPUP_IN_1S) {
idleCycleAll += g_cpup[g_idleTaskID].historyTime[curPos] -
g_cpup[g_idleTaskID].historyTime[prePos];
} else {
idleCycleAll += g_cpup[g_idleTaskID].allTime - g_cpup[g_idleTaskID].historyTime[curPos];
}
⑹ if (cpuCycleAll) {
cpupRet = (LOS_CPUP_PRECISION - (UINT32)((LOS_CPUP_PRECISION * idleCycleAll) / cpuCycleAll));
}
OsTskCycleStart();
LOS_IntRestore(intSave);
return cpupRet;
}
3.2.3 LOS_TaskCpuUsage
該函數會統計指定任務的CPU佔用率,和函數LOS_SysCpuUsage()代碼相似度高,可以參考上文對該函數的講解。
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskCpuUsage(UINT32 taskID)
{
UINT64 cpuCycleAll = 0;
UINT16 loopNum;
UINT32 intSave;
UINT32 cpupRet = 0;
if (g_cpupInitFlg == 0) {
return LOS_ERRNO_CPUP_NO_INIT;
}
if (OS_TSK_GET_INDEX(taskID) >= g_taskMaxNum) {
return LOS_ERRNO_CPUP_TSK_ID_INVALID;
}
if (g_cpup[taskID].cpupID != taskID) {
return LOS_ERRNO_CPUP_THREAD_NO_CREATED;
}
if ((g_cpup[taskID].status & OS_TASK_STATUS_UNUSED) || (g_cpup[taskID].status == 0)) {
return LOS_ERRNO_CPUP_THREAD_NO_CREATED;
}
intSave = LOS_IntLock();
OsTskCycleEnd();
for (loopNum = 0; loopNum < g_taskMaxNum; loopNum++) {
if ((g_cpup[loopNum].status & OS_TASK_STATUS_UNUSED) || (g_cpup[loopNum].status == 0)) {
continue;
}
cpuCycleAll += g_cpup[loopNum].allTime;
}
if (cpuCycleAll) {
cpupRet = (UINT32)((LOS_CPUP_PRECISION * g_cpup[taskID].allTime) / cpuCycleAll);
}
OsTskCycleStart();
LOS_IntRestore(intSave);
return cpupRet;
}
3.2.4 LOS_HistoryTaskCpuUsage
該函數獲取指定任務的歷史CPU佔用率,和函數LOS_HistorySysCpuUsage()代碼相似度高,可以參考上文對該函數的講解。
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_HistoryTaskCpuUsage(UINT32 taskID, UINT16 mode)
{
UINT64 cpuCycleAll = 0;
UINT64 cpuCycleCurTsk = 0;
UINT16 loopNum, curPos;
UINT16 prePos = 0;
UINT32 intSave;
UINT32 cpupRet = 0;
if (g_cpupInitFlg == 0) {
return LOS_ERRNO_CPUP_NO_INIT;
}
if (OS_TSK_GET_INDEX(taskID) >= g_taskMaxNum) {
return LOS_ERRNO_CPUP_TSK_ID_INVALID;
}
if (g_cpup[taskID].cpupID != taskID) {
return LOS_ERRNO_CPUP_THREAD_NO_CREATED;
}
if ((g_cpup[taskID].status & OS_TASK_STATUS_UNUSED) || (g_cpup[taskID].status == 0)) {
return LOS_ERRNO_CPUP_THREAD_NO_CREATED;
}
intSave = LOS_IntLock();
OsTskCycleEnd();
OsGetPositions(mode, &curPos, &prePos);
for (loopNum = 0; loopNum < g_taskMaxNum; loopNum++) {
if ((g_cpup[loopNum].status & OS_TASK_STATUS_UNUSED) || (g_cpup[loopNum].status == 0)) {
continue;
}
if (mode == CPUP_IN_1S) {
cpuCycleAll += g_cpup[loopNum].historyTime[curPos] - g_cpup[loopNum].historyTime[prePos];
} else {
cpuCycleAll += g_cpup[loopNum].allTime - g_cpup[loopNum].historyTime[curPos];
}
}
if (mode == CPUP_IN_1S) {
cpuCycleCurTsk += g_cpup[taskID].historyTime[curPos] - g_cpup[taskID].historyTime[prePos];
} else {
cpuCycleCurTsk += g_cpup[taskID].allTime - g_cpup[taskID].historyTime[curPos];
}
if (cpuCycleAll) {
cpupRet = (UINT32)((LOS_CPUP_PRECISION * cpuCycleCurTsk) / cpuCycleAll);
}
OsTskCycleStart();
LOS_IntRestore(intSave);
return cpupRet;
}
3.2.5 LOS_AllTaskCpuUsage
該函數獲取全部任務的CPU佔用率,獲取的CPU佔用率信息保存在傳出參數結構體CPUP_INFO_S *cpupInfo指向的內存區域裏,需要注意這個內存區域的大小需要等於sizeof(CPUP_INFO_S) * g_taskMaxNum。還需要傳入時間間隔模式參數,支持10秒、1秒、小於1秒三種。
⑴處先判斷CPUP是否已經初始化,如果沒有初始化過,返回錯誤碼。傳出參數cpupInfo指針不能爲空,否則返回錯誤碼。⑵處調用函數OsTskCycleEnd()獲取當前任務的結束時間,並計算出運行總時間。⑶處調用函數OsGetPositions()計算出歷史運行時間數組索引位置。⑷處計算出各個任務的週期內運行總時間,如果時間間隔模式爲1秒,取值兩個歷史運行時間之差,否則取值XX。⑸處設置每一個任務的狀態,然後計算出每一個任務的CPU佔用率。最後,調用函數OsTskCycleStart()設置新任務的CPUP統計的開始時間。
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_AllTaskCpuUsage(CPUP_INFO_S *cpupInfo, UINT16 mode)
{
UINT16 loopNum;
UINT16 curPos;
UINT16 prePos = 0;
UINT32 intSave;
UINT64 cpuCycleAll = 0;
UINT64 cpuCycleCurTsk = 0;
⑴ if (g_cpupInitFlg == 0) {
return LOS_ERRNO_CPUP_NO_INIT;
}
if (cpupInfo == NULL) {
return LOS_ERRNO_CPUP_TASK_PTR_NULL;
}
intSave = LOS_IntLock();
⑵ OsTskCycleEnd();
⑶ OsGetPositions(mode, &curPos, &prePos);
for (loopNum = 0; loopNum < g_taskMaxNum; loopNum++) {
if ((g_cpup[loopNum].status & OS_TASK_STATUS_UNUSED) ||
(g_cpup[loopNum].status == 0)) {
continue;
}
if (mode == CPUP_IN_1S) {
cpuCycleAll += g_cpup[loopNum].historyTime[curPos] - g_cpup[loopNum].historyTime[prePos];
} else {
cpuCycleAll += g_cpup[loopNum].allTime - g_cpup[loopNum].historyTime[curPos];
}
}
⑷ for (loopNum = 0; loopNum < g_taskMaxNum; loopNum++) {
if ((g_cpup[loopNum].status & OS_TASK_STATUS_UNUSED) ||
(g_cpup[loopNum].status == 0)) {
continue;
}
if (mode == CPUP_IN_1S) {
cpuCycleCurTsk += g_cpup[loopNum].historyTime[curPos] - g_cpup[loopNum].historyTime[prePos];
} else {
cpuCycleCurTsk += g_cpup[loopNum].allTime - g_cpup[loopNum].historyTime[curPos];
}
⑸ cpupInfo[loopNum].usStatus = g_cpup[loopNum].status;
if (cpuCycleAll) {
cpupInfo[loopNum].uwUsage = (UINT32)((LOS_CPUP_PRECISION * cpuCycleCurTsk) / cpuCycleAll);
}
cpuCycleCurTsk = 0;
}
OsTskCycleStart();
LOS_IntRestore(intSave);
return LOS_OK;
}
3.2.6 LOS_CpupUsageMonitor
該函數獲取歷史CPU佔用率並打印輸出,傳入參數有三個:CPU佔用率類型,CPUP時間週期模式,指定的任務編號。對於任務CPU佔用率,才需要指定有效的任務編號。
⑴處處理CPU佔用率類型爲系統CPU佔用率的情況,⑵處打印使用的CPUP時間週期模式。⑶處通過調用函數LOS_HistorySysCpuUsage()獲取系統歷史CPU佔用率,然後執行⑷打印輸出CPU佔用率結果,輸出結果範圍爲[0,100]。
⑸處處理CPU佔用率類型爲指定任務CPU佔用率的情況,首先判斷下任務編號的有效性,校驗任務是否創建等。⑹處打印使用的CPUP時間週期模式。⑺處通過調用函數LOS_HistoryTaskCpuUsage()獲取指定任務的歷史CPU佔用率,然後執行⑻打印輸出CPU佔用率結果,輸出結果範圍爲[0,100]。
LITE_OS_SEC_TEXT_MINOR UINT32 LOS_CpupUsageMonitor(CPUP_TYPE_E type, CPUP_MODE_E mode, UINT32 taskID)
{
UINT32 ret;
LosTaskCB *taskCB = NULL;
switch (type) {
⑴ case SYS_CPU_USAGE:
⑵ if (mode == CPUP_IN_10S) {
PRINTK("\nSysCpuUsage in 10s: ");
} else if (mode == CPUP_IN_1S) {
PRINTK("\nSysCpuUsage in 1s: ");
} else {
PRINTK("\nSysCpuUsage in <1s: ");
}
⑶ ret = LOS_HistorySysCpuUsage(mode);
⑷ PRINTK("%d.%d", ret / LOS_CPUP_PRECISION_MULT, ret % LOS_CPUP_PRECISION_MULT);
break;
⑸ case TASK_CPU_USAGE:
if (taskID > LOSCFG_BASE_CORE_TSK_LIMIT) {
PRINT_ERR("\nThe taskid is invalid.\n");
return OS_ERROR;
}
taskCB = OS_TCB_FROM_TID(taskID);
if ((taskCB->taskStatus & OS_TASK_STATUS_UNUSED)) {
PRINT_ERR("\nThe taskid is invalid.\n");
return OS_ERROR;
}
⑹ if (mode == CPUP_IN_10S) {
PRINTK("\nCPUusage of taskID %d in 10s: ", taskID);
} else if (mode == CPUP_IN_1S) {
PRINTK("\nCPUusage of taskID %d in 1s: ", taskID);
} else {
PRINTK("\nCPUusage of taskID %d in <1s: ", taskID);
}
⑺ ret = LOS_HistoryTaskCpuUsage(taskID, mode);
⑻ PRINTK("%u.%u", ret / LOS_CPUP_PRECISION_MULT, ret % LOS_CPUP_PRECISION_MULT);
break;
default:
PRINT_ERR("\nThe type is invalid.\n");
return OS_ERROR;
}
return LOS_OK;
}
小結
本文帶領大家一起剖析了鴻蒙輕內核的CPUP擴展模塊的源代碼。感謝閱讀,如有任何問題、建議,都可以博客下留言給我,謝謝。