鸿蒙轻内核M核源码分析系列十五CPU使用率CPUP

开发 前端
CPUP(Central Processing Unit Percentage,CPU占用率)分为系统CPU占用率和任务CPU占用率。用户通过系统级的CPU占用率,判断当前系统负载是否超出设计规格。

[[409327]]

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

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扩展模块的源码。

CPUP模块用任务级记录的方式,在任务切换时,记录任务启动时间,任务切出或者退出时间,每次当任务退出时,系统会累加整个任务的占用时间。接下来,我们看下CPUP模块支持的常见操作的源代码。

1、CPUP结构体定义和常用宏定义

1.1 CPUP结构体定义

在文件components\cpup\los_cpup.h定义的CPUP控制块结构体为OsCpupCB,结构体源代码如下,allTime记录该任务自系统启动以来运行的cycle数,startTime记录任务开始运行的时间,historyTime[]历史运行时间数组的10个元素记录最近10秒中每一秒中每个任务自系统启动以来运行的cycle数,其他结构体成员的解释见注释部分。

  1. typedef struct { 
  2.     UINT32 cpupID;                                        /**< 任务编号 */ 
  3.     UINT16 status;                                        /**< 任务状态 */ 
  4.     UINT64 allTime;                                       /**< 总共运行的时间 */ 
  5.     UINT64 startTime;                                     /**< 任务开始时间 */ 
  6.     UINT64 historyTime[OS_CPUP_HISTORY_RECORD_NUM];       /**< 历史运行时间数组,其中OS_CPUP_HISTORY_RECORD_NUM为10 */ 
  7. } OsCpupCB; 

另外,还定义了一个结构体CPUP_INFO_S,如下:

  1. typedef struct tagCpupInfo { 
  2.     UINT16 usStatus;            /**< 保存当前运行任务状态           */ 
  3.     UINT32 uwUsage;             /**< 使用情况,值范围为 [0,1000].   */ 
  4. } CPUP_INFO_S; 

1.2 CPUP枚举定义

CPUP头文件components\cpup\los_cpup.h中还提供了相关的枚举,CPUP占用率类型CPUP_TYPE_E,及CPUP统计时间间隔模式CPUP_MODE_E。

  1. typedef enum { 
  2.     SYS_CPU_USAGE = 0,   /* 系统CPUP */ 
  3.     TASK_CPU_USAGE,      /* 任务CPUP */ 
  4. } CPUP_TYPE_E; 
  5.  
  6. typedef enum { 
  7.     CPUP_IN_10S = 0,     /* CPUP统计周期10s */ 
  8.     CPUP_IN_1S,          /* CPUP统计周期1s */ 
  9.     CPUP_LESS_THAN_1S,   /* CPUP统计周期<1s */ 
  10. } CPUP_MODE_E; 

2、CPUP初始化

CPUP默认关闭,用户可以通过宏LOSCFG_BASE_CORE_CPUP进行开启。开启CPUP的情况下,在系统启动时,在kernel\src\los_init.c中调用OsCpupInit()进行CPUP模块初始化。下面,我们分析下CPUP初始化的代码。

⑴处计算CPUP结构体池需要的内存大小,然后为CPUP申请内存,如果申请失败,则返回错误。⑵处初始化成功后,设置初始化标记g_cpupInitFlg。

  1. LITE_OS_SEC_TEXT_INIT UINT32 OsCpupInit() 
  2.     UINT32 size
  3.  
  4.     size = g_taskMaxNum * sizeof(OsCpupCB); 
  5. ⑴  g_cpup = (OsCpupCB *)LOS_MemAlloc(m_aucSysMem0, size); 
  6.  
  7.     if (g_cpup == NULL) { 
  8.         return LOS_ERRNO_CPUP_NO_MEMORY; 
  9.     } 
  10.  
  11.     (VOID)memset_s(g_cpup, size, 0, size); 
  12. ⑵  g_cpupInitFlg = 1; 
  13.  
  14.     return LOS_OK; 

3、CPUP常用操作

3.1 CPUP内部接口

我们先分析下内部接口,这些接口会被LOS_开头的外部接口调用。

3.1.1 OsTskCycleStart记录任务开始时间

CPUP模块对外接口执行后期会调用该内部接口,设置下一个任务的开始运行时间。

⑴处先判断CPUP是否已经初始化,如果没有初始化过,退出该函数的执行。⑵处获取新任务的任务编号。⑶处设置该任务对应的CPUP结构体的任务编号和开始时间。

  1. LITE_OS_SEC_TEXT_MINOR VOID OsTskCycleStart(VOID) 
  2.     UINT32 taskID; 
  3.  
  4. ⑴  if (g_cpupInitFlg == 0) { 
  5.         return
  6.     } 
  7.  
  8. ⑵  taskID = g_losTask.newTask->taskID; 
  9. ⑶  g_cpup[taskID].cpupID = taskID; 
  10.     g_cpup[taskID].startTime = LOS_SysCycleGet(); 
  11.  
  12.     return

3.1.2 OsTskCycleEnd记录任务结束时间

CPUP模块对外接口执行前期会调用该内部接口,获取当前任务的结束时间,并统计当前任务的运行总时间。

⑴处先判断CPUP是否已经初始化,如果没有初始化过,退出该函数的执行。⑵处获取当前任务的任务编号。⑶处如果该任务的开始时间为0,退出函数执行。⑷处获取系统的当前cycle数。⑸如果获取的小于任务CPUP开始时间,则把获取的cycle数加上每个tick的cycle数。⑹处计算当前任务的运行的总时间,然后把开始时间置0。

  1. LITE_OS_SEC_TEXT_MINOR VOID OsTskCycleEnd(VOID) 
  2.     UINT32 taskID; 
  3.     UINT64 cpuCycle; 
  4.  
  5. ⑴  if (g_cpupInitFlg == 0) { 
  6.         return
  7.     } 
  8.  
  9. ⑵  taskID = g_losTask.runTask->taskID; 
  10.  
  11. ⑶  if (g_cpup[taskID].startTime == 0) { 
  12.         return
  13.     } 
  14.  
  15. ⑷  cpuCycle = LOS_SysCycleGet(); 
  16.  
  17. ⑸  if (cpuCycle < g_cpup[taskID].startTime) { 
  18.         cpuCycle += g_cyclesPerTick; 
  19.     } 
  20.  
  21. ⑹  g_cpup[taskID].allTime += (cpuCycle - g_cpup[taskID].startTime); 
  22.     g_cpup[taskID].startTime = 0; 
  23.  
  24.     return

3.1.3 OsTskCycleEndStart任务切换时更新任务历史运行时间

该函数在任务调度切换时会被执行,计算当前运行任务的运行总时间,记录新任务的开始时间,并更新所有任务的历史运行时间。函数的示意图如下:

鸿蒙轻内核M核源码分析系列十五 CPU使用率CPUP-鸿蒙HarmonyOS技术社区

⑴处先判断CPUP是否已经初始化,如果没有初始化过,退出该函数的执行。

⑵处获取当前任务的任务编号,然后获取系统的当前cycle数。

⑶处如果当前任务的开始时间不为0,则计算当前任务的运行的总时间,然后把开始时间置0。

⑷处获取新任务的任务编号。

⑸处设置该任务对应的CPUP结构体的任务编号和开始时间。

⑹处如果记录间隔大于系统时钟(即每秒的cycle数),更新上次记录时间。这意味着每个任务的historyTime[]数组中的每个元素表示1s多的周期内该任务的运行cycle数量,并不是非常精确的。然后执行⑺,记录每一个任务对应的CPUP的历史运行时间。⑻处更新历史运行时间数组的当前索引值。

  1. LITE_OS_SEC_TEXT_MINOR VOID OsTskCycleEndStart(VOID) 
  2.     UINT32 taskID; 
  3.     UINT64 cpuCycle; 
  4.     UINT16 loopNum; 
  5.  
  6. ⑴  if (g_cpupInitFlg == 0) { 
  7.         return
  8.     } 
  9.  
  10. ⑵  taskID = g_losTask.runTask->taskID; 
  11.     cpuCycle = LOS_SysCycleGet(); 
  12.  
  13. ⑶  if (g_cpup[taskID].startTime != 0) { 
  14.         if (cpuCycle < g_cpup[taskID].startTime) { 
  15.             cpuCycle += g_cyclesPerTick; 
  16.         } 
  17.  
  18.         g_cpup[taskID].allTime += (cpuCycle - g_cpup[taskID].startTime); 
  19.         g_cpup[taskID].startTime = 0; 
  20.     } 
  21.  
  22. ⑷  taskID = g_losTask.newTask->taskID; 
  23. ⑸  g_cpup[taskID].cpupID = taskID; 
  24.     g_cpup[taskID].startTime = cpuCycle; 
  25.  
  26. ⑹  if ((cpuCycle - g_lastRecordTime) > OS_CPUP_RECORD_PERIOD) { 
  27.         g_lastRecordTime = cpuCycle; 
  28.  
  29.         for (loopNum = 0; loopNum < g_taskMaxNum; loopNum++) { 
  30. ⑺          g_cpup[loopNum].historyTime[g_hisPos] = g_cpup[loopNum].allTime; 
  31.         } 
  32.  
  33. ⑻      if (g_hisPos == (OS_CPUP_HISTORY_RECORD_NUM - 1)) { 
  34.             g_hisPos = 0; 
  35.         } else { 
  36.             g_hisPos++; 
  37.         } 
  38.     } 
  39.  
  40.     return

3.1.4 OsGetPrePos获取历史运行时间数组上一索引位置

代码比较简单,如果传入参数curPos为0,则返回数组的最后一个索引位置OS_CPUP_HISTORY_RECORD_NUM - 1。否则返回减1返回。

  1. LITE_OS_SEC_TEXT_MINOR static inline UINT16 OsGetPrePos(UINT16 curPos) 
  2.     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。⑷处设置传出参数。

  1. LITE_OS_SEC_TEXT_MINOR static VOID OsGetPositions(UINT16 mode, UINT16* curPosAddr, UINT16* prePosAddr) 
  2.     UINT16 curPos; 
  3.     UINT16 prePos = 0; 
  4.  
  5. ⑴  curPos = g_hisPos; 
  6.  
  7. ⑵  if (mode == CPUP_IN_1S) { 
  8.         curPos = OsGetPrePos(curPos); 
  9.         prePos = OsGetPrePos(curPos); 
  10. ⑶  } else if (mode == CPUP_LESS_THAN_1S) { 
  11.         curPos = OsGetPrePos(curPos); 
  12.     } 
  13.  
  14. ⑷  *curPosAddr = curPos; 
  15.     *prePosAddr = prePos; 

3.2 CPUP对外接口

我们先分析下外部接口,接口说明如下:

3.2.1 LOS_SysCpuUsage

该函数会统计当前系统CPU占用率,返回值基于千分率计算,取值范围为[0,1000]。函数的示意图如下:

鸿蒙轻内核M核源码分析系列十五 CPU使用率CPUP-鸿蒙HarmonyOS技术社区

⑴处先判断CPUP是否已经初始化,如果没有初始化过,返回错误码。

⑵处调用函数OsTskCycleEnd()获取当前任务的结束时间,并计算出运行总时间。

⑶处统计所有任务的运行总时间,如果总时间不为0,执行⑷计算出系统的任务CPU占用率。

⑸处调用函数OsTskCycleStart()设置新任务的CPUP统计的开始时间。

  1. LITE_OS_SEC_TEXT_MINOR UINT32 LOS_SysCpuUsage(VOID) 
  2.     UINT64  cpuCycleAll = 0; 
  3.     UINT32  cpupRet = 0; 
  4.     UINT16  loopNum; 
  5.     UINT32 intSave; 
  6.  
  7. ⑴  if (g_cpupInitFlg == 0) { 
  8.         return LOS_ERRNO_CPUP_NO_INIT; 
  9.     } 
  10.  
  11.     intSave = LOS_IntLock(); 
  12. ⑵  OsTskCycleEnd(); 
  13.  
  14. ⑶  for (loopNum = 0; loopNum < g_taskMaxNum; loopNum++) { 
  15.         cpuCycleAll += g_cpup[loopNum].allTime; 
  16.     } 
  17.  
  18. ⑷  if (cpuCycleAll) { 
  19.         cpupRet = LOS_CPUP_PRECISION -  (UINT32)((LOS_CPUP_PRECISION * 
  20.             g_cpup[g_idleTaskID].allTime) / cpuCycleAll); 
  21.     } 
  22.  
  23. ⑸  OsTskCycleStart(); 
  24.     LOS_IntRestore(intSave); 
  25.  
  26.     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统计的开始时间。可以参考示意图进行理解:

鸿蒙轻内核M核源码分析系列十五 CPU使用率CPUP-鸿蒙HarmonyOS技术社区
  1. LITE_OS_SEC_TEXT_MINOR UINT32 LOS_HistorySysCpuUsage(UINT16 mode) 
  2.     UINT64  cpuCycleAll = 0; 
  3.     UINT64  idleCycleAll = 0; 
  4.     UINT32  cpupRet = 0; 
  5.     UINT16  loopNum; 
  6.     UINT16  curPos; 
  7.     UINT16  prePos = 0; 
  8.     UINT32 intSave; 
  9.  
  10. ⑴  if (g_cpupInitFlg == 0) { 
  11.         return LOS_ERRNO_CPUP_NO_INIT; 
  12.     } 
  13.  
  14.     // get end time of current task 
  15.     intSave = LOS_IntLock(); 
  16. ⑵  OsTskCycleEnd(); 
  17.  
  18. ⑶  OsGetPositions(mode, &curPos, &prePos); 
  19.  
  20.     for (loopNum = 0; loopNum < g_taskMaxNum; loopNum++) { 
  21. ⑷      if (mode == CPUP_IN_1S) { 
  22.             cpuCycleAll += g_cpup[loopNum].historyTime[curPos] - g_cpup[loopNum].historyTime[prePos]; 
  23.         } else { 
  24.             cpuCycleAll += g_cpup[loopNum].allTime - g_cpup[loopNum].historyTime[curPos]; 
  25.         } 
  26.     } 
  27.  
  28. ⑸  if (mode == CPUP_IN_1S) { 
  29.         idleCycleAll += g_cpup[g_idleTaskID].historyTime[curPos] - 
  30.                            g_cpup[g_idleTaskID].historyTime[prePos]; 
  31.     } else { 
  32.         idleCycleAll += g_cpup[g_idleTaskID].allTime - g_cpup[g_idleTaskID].historyTime[curPos]; 
  33.     } 
  34.  
  35. ⑹  if (cpuCycleAll) { 
  36.         cpupRet = (LOS_CPUP_PRECISION -  (UINT32)((LOS_CPUP_PRECISION * idleCycleAll) / cpuCycleAll)); 
  37.     } 
  38.  
  39.     OsTskCycleStart(); 
  40.     LOS_IntRestore(intSave); 
  41.  
  42.     return cpupRet; 

3.2.3 LOS_TaskCpuUsage

该函数会统计指定任务的CPU占用率,和函数LOS_SysCpuUsage()代码相似度高,可以参考上文对该函数的讲解。

  1. LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskCpuUsage(UINT32 taskID) 
  2.     UINT64  cpuCycleAll = 0; 
  3.     UINT16  loopNum; 
  4.     UINT32 intSave; 
  5.     UINT32  cpupRet = 0; 
  6.  
  7.     if (g_cpupInitFlg == 0) { 
  8.         return LOS_ERRNO_CPUP_NO_INIT; 
  9.     } 
  10.     if (OS_TSK_GET_INDEX(taskID) >= g_taskMaxNum) { 
  11.         return LOS_ERRNO_CPUP_TSK_ID_INVALID; 
  12.     } 
  13.     if (g_cpup[taskID].cpupID != taskID) { 
  14.         return LOS_ERRNO_CPUP_THREAD_NO_CREATED; 
  15.     } 
  16.     if ((g_cpup[taskID].status & OS_TASK_STATUS_UNUSED) || (g_cpup[taskID].status == 0)) { 
  17.         return LOS_ERRNO_CPUP_THREAD_NO_CREATED; 
  18.     } 
  19.     intSave = LOS_IntLock(); 
  20.     OsTskCycleEnd(); 
  21.  
  22.     for (loopNum = 0; loopNum < g_taskMaxNum; loopNum++) { 
  23.         if ((g_cpup[loopNum].status & OS_TASK_STATUS_UNUSED) || (g_cpup[loopNum].status == 0)) { 
  24.             continue
  25.         } 
  26.         cpuCycleAll += g_cpup[loopNum].allTime; 
  27.     } 
  28.  
  29.     if (cpuCycleAll) { 
  30.         cpupRet = (UINT32)((LOS_CPUP_PRECISION * g_cpup[taskID].allTime) / cpuCycleAll); 
  31.     } 
  32.  
  33.     OsTskCycleStart(); 
  34.     LOS_IntRestore(intSave); 
  35.  
  36.     return cpupRet; 

3.2.4 LOS_HistoryTaskCpuUsage

该函数获取指定任务的历史CPU占用率,和函数LOS_HistorySysCpuUsage()代码相似度高,可以参考上文对该函数的讲解。

  1. LITE_OS_SEC_TEXT_MINOR UINT32 LOS_HistoryTaskCpuUsage(UINT32 taskID, UINT16 mode) 
  2.     UINT64  cpuCycleAll = 0; 
  3.     UINT64  cpuCycleCurTsk = 0; 
  4.     UINT16  loopNum, curPos; 
  5.     UINT16  prePos = 0; 
  6.     UINT32 intSave; 
  7.     UINT32  cpupRet = 0; 
  8.  
  9.    if (g_cpupInitFlg == 0) { 
  10.         return LOS_ERRNO_CPUP_NO_INIT; 
  11.     } 
  12.     if (OS_TSK_GET_INDEX(taskID) >= g_taskMaxNum) { 
  13.         return LOS_ERRNO_CPUP_TSK_ID_INVALID; 
  14.     } 
  15.     if (g_cpup[taskID].cpupID != taskID) { 
  16.         return LOS_ERRNO_CPUP_THREAD_NO_CREATED; 
  17.     } 
  18.     if ((g_cpup[taskID].status & OS_TASK_STATUS_UNUSED) || (g_cpup[taskID].status == 0)) { 
  19.         return LOS_ERRNO_CPUP_THREAD_NO_CREATED; 
  20.     } 
  21.     intSave = LOS_IntLock(); 
  22.     OsTskCycleEnd(); 
  23.  
  24.     OsGetPositions(mode, &curPos, &prePos); 
  25.  
  26.     for (loopNum = 0; loopNum < g_taskMaxNum; loopNum++) { 
  27.         if ((g_cpup[loopNum].status & OS_TASK_STATUS_UNUSED) || (g_cpup[loopNum].status == 0)) { 
  28.             continue
  29.         } 
  30.  
  31.         if (mode == CPUP_IN_1S) { 
  32.             cpuCycleAll += g_cpup[loopNum].historyTime[curPos] - g_cpup[loopNum].historyTime[prePos]; 
  33.         } else { 
  34.             cpuCycleAll += g_cpup[loopNum].allTime - g_cpup[loopNum].historyTime[curPos]; 
  35.         } 
  36.     } 
  37.  
  38.     if (mode == CPUP_IN_1S) { 
  39.         cpuCycleCurTsk += g_cpup[taskID].historyTime[curPos] - g_cpup[taskID].historyTime[prePos]; 
  40.     } else { 
  41.         cpuCycleCurTsk += g_cpup[taskID].allTime - g_cpup[taskID].historyTime[curPos]; 
  42.     } 
  43.     if (cpuCycleAll) { 
  44.         cpupRet = (UINT32)((LOS_CPUP_PRECISION * cpuCycleCurTsk) / cpuCycleAll); 
  45.     } 
  46.  
  47.     OsTskCycleStart(); 
  48.     LOS_IntRestore(intSave); 
  49.  
  50.     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统计的开始时间。

  1. LITE_OS_SEC_TEXT_MINOR UINT32 LOS_AllTaskCpuUsage(CPUP_INFO_S *cpupInfo, UINT16 mode) 
  2.     UINT16  loopNum; 
  3.     UINT16  curPos; 
  4.     UINT16  prePos = 0; 
  5.     UINT32 intSave; 
  6.     UINT64  cpuCycleAll = 0; 
  7.     UINT64  cpuCycleCurTsk = 0; 
  8.  
  9. ⑴  if (g_cpupInitFlg == 0) { 
  10.         return  LOS_ERRNO_CPUP_NO_INIT; 
  11.     } 
  12.  
  13.     if (cpupInfo == NULL) { 
  14.         return LOS_ERRNO_CPUP_TASK_PTR_NULL; 
  15.     } 
  16.  
  17.     intSave = LOS_IntLock(); 
  18. ⑵  OsTskCycleEnd(); 
  19.  
  20. ⑶  OsGetPositions(mode, &curPos, &prePos); 
  21.  
  22.     for (loopNum = 0; loopNum < g_taskMaxNum; loopNum++) { 
  23.         if ((g_cpup[loopNum].status & OS_TASK_STATUS_UNUSED) || 
  24.             (g_cpup[loopNum].status == 0)) { 
  25.             continue
  26.         } 
  27.  
  28.         if (mode == CPUP_IN_1S) { 
  29.             cpuCycleAll += g_cpup[loopNum].historyTime[curPos] - g_cpup[loopNum].historyTime[prePos]; 
  30.         } else { 
  31.             cpuCycleAll += g_cpup[loopNum].allTime - g_cpup[loopNum].historyTime[curPos]; 
  32.         } 
  33.     } 
  34.  
  35. ⑷  for (loopNum = 0; loopNum < g_taskMaxNum; loopNum++) { 
  36.         if ((g_cpup[loopNum].status & OS_TASK_STATUS_UNUSED) || 
  37.             (g_cpup[loopNum].status == 0)) { 
  38.             continue
  39.         } 
  40.  
  41.         if (mode == CPUP_IN_1S) { 
  42.             cpuCycleCurTsk += g_cpup[loopNum].historyTime[curPos] - g_cpup[loopNum].historyTime[prePos]; 
  43.         } else { 
  44.             cpuCycleCurTsk += g_cpup[loopNum].allTime - g_cpup[loopNum].historyTime[curPos]; 
  45.         } 
  46. ⑸      cpupInfo[loopNum].usStatus = g_cpup[loopNum].status; 
  47.         if (cpuCycleAll) { 
  48.             cpupInfo[loopNum].uwUsage = (UINT32)((LOS_CPUP_PRECISION * cpuCycleCurTsk) / cpuCycleAll); 
  49.         } 
  50.  
  51.         cpuCycleCurTsk = 0; 
  52.     } 
  53.  
  54.     OsTskCycleStart(); 
  55.     LOS_IntRestore(intSave); 
  56.  
  57.     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]。

  1. LITE_OS_SEC_TEXT_MINOR UINT32 LOS_CpupUsageMonitor(CPUP_TYPE_E type, CPUP_MODE_E mode, UINT32 taskID) 
  2.     UINT32 ret; 
  3.     LosTaskCB *taskCB = NULL
  4.  
  5.     switch (type) { 
  6. ⑴      case SYS_CPU_USAGE: 
  7. ⑵          if (mode == CPUP_IN_10S) { 
  8.                 PRINTK("\nSysCpuUsage in 10s: "); 
  9.             } else if (mode == CPUP_IN_1S) { 
  10.                 PRINTK("\nSysCpuUsage in 1s: "); 
  11.             } else { 
  12.                 PRINTK("\nSysCpuUsage in <1s: "); 
  13.             } 
  14. ⑶          ret = LOS_HistorySysCpuUsage(mode); 
  15. ⑷          PRINTK("%d.%d", ret / LOS_CPUP_PRECISION_MULT, ret % LOS_CPUP_PRECISION_MULT); 
  16.             break; 
  17.  
  18. ⑸      case TASK_CPU_USAGE: 
  19.             if (taskID > LOSCFG_BASE_CORE_TSK_LIMIT) { 
  20.                 PRINT_ERR("\nThe taskid is invalid.\n"); 
  21.                 return OS_ERROR; 
  22.             } 
  23.             taskCB = OS_TCB_FROM_TID(taskID); 
  24.             if ((taskCB->taskStatus & OS_TASK_STATUS_UNUSED)) { 
  25.                 PRINT_ERR("\nThe taskid is invalid.\n"); 
  26.                 return OS_ERROR; 
  27.             } 
  28. ⑹          if (mode == CPUP_IN_10S) { 
  29.                 PRINTK("\nCPUusage of taskID %d in 10s: ", taskID); 
  30.             } else if (mode == CPUP_IN_1S) { 
  31.                 PRINTK("\nCPUusage of taskID %d in 1s: ", taskID); 
  32.             } else { 
  33.                 PRINTK("\nCPUusage of taskID %d in <1s: ", taskID); 
  34.             } 
  35. ⑺          ret = LOS_HistoryTaskCpuUsage(taskID, mode); 
  36. ⑻          PRINTK("%u.%u", ret / LOS_CPUP_PRECISION_MULT, ret % LOS_CPUP_PRECISION_MULT); 
  37.             break; 
  38.  
  39.         default
  40.             PRINT_ERR("\nThe type is invalid.\n"); 
  41.             return OS_ERROR; 
  42.     } 
  43.  
  44.     return LOS_OK; 

小结

本文带领大家一起剖析了鸿蒙轻内核的CPUP扩展模块的源代码。

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

 

责任编辑:jianghua 来源: 鸿蒙社区
相关推荐

2021-06-04 09:57:49

鸿蒙HarmonyOS应用

2022-01-12 10:50:23

鸿蒙HarmonyOS应用

2022-01-10 15:31:44

鸿蒙HarmonyOS应用

2021-10-20 16:08:57

鸿蒙HarmonyOS应用

2021-05-25 09:28:34

鸿蒙HarmonyOS应用

2021-05-17 09:28:59

鸿蒙HarmonyOS应用

2021-06-04 14:15:10

鸿蒙HarmonyOS应用

2021-05-08 15:14:50

鸿蒙HarmonyOS应用

2021-05-31 20:30:55

鸿蒙HarmonyOS应用

2022-04-13 11:02:12

鸿蒙事件模块事件Event

2022-03-03 18:28:28

Harmony进程任务管理模块

2022-03-11 20:23:14

鸿蒙源码分析进程管理

2021-06-09 09:48:01

鸿蒙HarmonyOS应用

2021-05-21 09:25:11

鸿蒙HarmonyOS应用

2021-05-27 09:43:56

鸿蒙HarmonyOS应用

2021-05-11 09:54:55

鸿蒙HarmonyOS应用

2021-09-22 14:36:32

鸿蒙HarmonyOS应用

2021-05-12 09:45:20

鸿蒙HarmonyOS应用

2021-05-10 15:05:56

鸿蒙HarmonyOS应用

2021-04-30 15:06:34

鸿蒙HarmonyOS应用
点赞
收藏

51CTO技术栈公众号