提交 9d26af26 编写于 作者: 鸿蒙内核源码分析's avatar 鸿蒙内核源码分析

CPU的工作量是如何分配的, 读懂对 SortLinkList 的注解即可

    百万汉字注解 + 百篇博客分析 => 挖透鸿蒙内核源码
    博客输出站点(国内):http://weharmonyos.com
    博客输出站点(国外):https://weharmony.github.io
    注解文件系统:https://gitee.com/weharmony/third_party_NuttX
    注解协议栈:https://gitee.com/weharmony/third_party_lwip
    注解编译子系统:https://gitee.com/weharmony/build_lite
上级 aa36c1c9
......@@ -58,7 +58,7 @@ typedef enum {
* 这样做的好处是,在多处理器系统中,当处理器操作属于它的变量副本时,不需要考虑与其他处理器的竞争的问题,
*/
typedef struct {
SortLinkAttribute taskSortLink; /*! task sort link | 挂等待和延时的任务 */
SortLinkAttribute taskSortLink; /*! task sort link | 挂等待和延时的任务,这些任务从任务就绪队列中来,等待最后CPU执行 */
SPIN_LOCK_S taskSortLinkSpin; ///< task sort link spin lock | 操作taskSortLink链表的自旋锁
SortLinkAttribute swtmrSortLink; ///< swtmr sort link | 挂还没到时间的定时器
SPIN_LOCK_S swtmrSortLinkSpin; ///< swtmr sort link spin lock |* 操作swtmrSortLink链表的自旋锁
......@@ -74,7 +74,7 @@ typedef struct {
#ifdef LOSCFG_KERNEL_SMP
UINT32 excFlag; ///< cpu halt or exc flag | cpu 停止或 异常 标志
#ifdef LOSCFG_KERNEL_SMP_CALL
LOS_DL_LIST funcLink; ///< mp function call link
LOS_DL_LIST funcLink; ///< mp function call link | 回调函数
#endif
#endif
} Percpu;
......
......@@ -167,7 +167,7 @@ typedef struct ProcessCB {
*
* The process is running.
*/
#define OS_PROCESS_STATUS_RUNNING 0x0040U ///< 进程运行状态
#define OS_PROCESS_STATUS_RUNNING 0x0040U ///< 进程状态: 运行中...
/**
* @ingroup los_process
......@@ -175,7 +175,7 @@ typedef struct ProcessCB {
*
* The process is pending
*/
#define OS_PROCESS_STATUS_PENDING 0x0080U
#define OS_PROCESS_STATUS_PENDING 0x0080U ///< 进程状态: 挂起中... ,意思是进程还没开始,在等待其他条件成熟
/**
* @ingroup los_process
......@@ -183,7 +183,7 @@ typedef struct ProcessCB {
*
* The process is run out but the resources occupied by the process are not recovered.
*/
#define OS_PROCESS_STATUS_ZOMBIES 0x100U ///< 进程僵死状态
#define OS_PROCESS_STATUS_ZOMBIES 0x100U ///< 进程状态: 僵死
/**
* @ingroup los_process
......@@ -239,9 +239,9 @@ typedef struct ProcessCB {
* Flag that indicates the process or process control block status.
*
* The process is dying or already dying.
*/
*/ /// 进程不活跃状态定义: 身上贴有退出便签且状态为僵死的进程
#define OS_PROCESS_STATUS_INACTIVE (OS_PROCESS_FLAG_EXIT | OS_PROCESS_STATUS_ZOMBIES)
//进程不活跃状态定义: 身上贴有退出便签且状态为僵死的进程
/**
* @ingroup los_process
* Used to check if the process control block is unused.
......@@ -254,44 +254,44 @@ STATIC INLINE BOOL OsProcessIsUnused(const LosProcessCB *processCB)//查下进
/**
* @ingroup los_process
* Used to check if the process is inactive.
*/
*/ /// 进程不活跃函数定义:身上贴有不使用且不活跃标签的进程
STATIC INLINE BOOL OsProcessIsInactive(const LosProcessCB *processCB)//查下进程是否不活跃?
{
return ((processCB->processStatus & (OS_PROCESS_FLAG_UNUSED | OS_PROCESS_STATUS_INACTIVE)) != 0);
}//进程不活跃函数定义:身上贴有不使用且不活跃标签的进程
}
/**
* @ingroup los_process
* Used to check if the process is dead.
*/
*/ /// 进程死啦死啦的定义: 身上贴有不使用且状态为僵死的进程
STATIC INLINE BOOL OsProcessIsDead(const LosProcessCB *processCB)//查下进程是否死啦死啦滴?
{
return ((processCB->processStatus & (OS_PROCESS_FLAG_UNUSED | OS_PROCESS_STATUS_ZOMBIES)) != 0);
}//进程死啦死啦的定义: 身上贴有不使用且状态为僵死的进程
}
/**
* @ingroup los_process
* The highest priority of a kernel mode process.
*/
#define OS_PROCESS_PRIORITY_HIGHEST 0 //进程最高优先级
#define OS_PROCESS_PRIORITY_HIGHEST 0 ///< 进程最高优先级
/**
* @ingroup los_process
* The lowest priority of a kernel mode process
*/
#define OS_PROCESS_PRIORITY_LOWEST 31 //进程最低优先级
#define OS_PROCESS_PRIORITY_LOWEST 31 ///< 进程最低优先级
/**
* @ingroup los_process
* The highest priority of a user mode process.
*/
#define OS_USER_PROCESS_PRIORITY_HIGHEST 10 //内核模式和用户模式的优先级分割线 10-31 用户级, 0-9内核级
#define OS_USER_PROCESS_PRIORITY_HIGHEST 10 ///< 内核模式和用户模式的优先级分割线 10-31 用户级, 0-9内核级
/**
* @ingroup los_process
* The lowest priority of a user mode process
*/
#define OS_USER_PROCESS_PRIORITY_LOWEST OS_PROCESS_PRIORITY_LOWEST //用户进程的最低优先级
#define OS_USER_PROCESS_PRIORITY_LOWEST OS_PROCESS_PRIORITY_LOWEST ///< 用户进程的最低优先级
/**
* @ingroup los_process
......@@ -339,7 +339,7 @@ STATIC INLINE BOOL OsProcessIsUserMode(const LosProcessCB *processCB)
* | | exit code | core dump | signal |
*/
#define OS_PRO_EXIT_OK 0 ///< 进程正常退出
//置进程退出码第七位为1
/// 置进程退出码第七位为1
STATIC INLINE VOID OsProcessExitCodeCoreDumpSet(LosProcessCB *processCB)
{
processCB->exitCode |= 0x80U; // 0b10000000
......
......@@ -45,8 +45,8 @@ extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#define OS_SCHED_MINI_PERIOD (OS_SYS_CLOCK / LOSCFG_BASE_CORE_TICK_PER_SECOND_MINI)
#define OS_TICK_RESPONSE_PRECISION (UINT32)((OS_SCHED_MINI_PERIOD * 75) / 100)
#define OS_SCHED_MINI_PERIOD (OS_SYS_CLOCK / LOSCFG_BASE_CORE_TICK_PER_SECOND_MINI) ///< 1毫秒的时钟周期
#define OS_TICK_RESPONSE_PRECISION (UINT32)((OS_SCHED_MINI_PERIOD * 75) / 100) ///< 不明白为啥是 * 75 就精确了??? @note_thinking
#define OS_SCHED_MAX_RESPONSE_TIME (UINT64)(((UINT64)-1) - 1U)
extern UINT32 g_taskScheduled;
......@@ -62,17 +62,17 @@ STATIC INLINE UINT64 OsGetCurrSchedTimeCycle(VOID)
return 0;
}
/// 更新中断使用时间
STATIC INLINE VOID OsSchedIrqUpdateUsedTime(VOID)
{
LosTaskCB *runTask = OsCurrTaskGet();
runTask->irqUsedTime = OsGetCurrSchedTimeCycle() - runTask->irqStartTime;
runTask->irqUsedTime = OsGetCurrSchedTimeCycle() - runTask->irqStartTime;//获取时间差
}
/// 获取中断开始时间
STATIC INLINE VOID OsSchedIrqStartTime(VOID)
{
LosTaskCB *runTask = OsCurrTaskGet();
runTask->irqStartTime = OsGetCurrSchedTimeCycle();
runTask->irqStartTime = OsGetCurrSchedTimeCycle(); //获取当前时间
}
/*
......@@ -87,12 +87,12 @@ STATIC INLINE VOID OsSchedIrqStartTime(VOID)
g_taskScheduled &= ~(1U << (cpuid)); \
} while (0);
#define OS_SCHEDULER_ACTIVE (g_taskScheduled & (1U << ArchCurrCpuid()))//用于判断当前cpu是否可调度
#define OS_SCHEDULER_ACTIVE (g_taskScheduled & (1U << ArchCurrCpuid()))///< 用于判断当前cpu是否在调度中
typedef enum {
INT_NO_RESCH = 0x0, /* no needs to schedule */
INT_PEND_RESCH = 0x1, /* pending schedule flag */
INT_PEND_TICK = 0x2, /* pending tick */
INT_NO_RESCH = 0x0, /**< no needs to schedule | 不需要调度*/
INT_PEND_RESCH = 0x1, /**< pending schedule flag | 因不允许抢占或正在中断导致的不允许调度*/
INT_PEND_TICK = 0x2, /**< pending tick | 更新过期时间遇到正在中断导致的不允许调度*/
} SchedFlag;
/* Check if preemptable with counter flag */
......@@ -122,7 +122,7 @@ STATIC INLINE BOOL OsPreemptableInSched(VOID)
#ifdef LOSCFG_KERNEL_SMP
/*
* For smp systems, schedule must hold the task spinlock, and this counter
* will increase by 1 in that case.
* will increase by 1 in that case. | 对于 smp ,调度必须持有任务自旋锁,在这种情况下,此计数器将增加 1。
*/
preemptable = (OsPercpuGet()->taskLockCnt == 1);//SMP时 taskLockCnt=1 才能执行调度任务
......@@ -130,18 +130,18 @@ STATIC INLINE BOOL OsPreemptableInSched(VOID)
preemptable = (OsPercpuGet()->taskLockCnt == 0);
#endif
if (!preemptable) {
/* Set schedule flag if preemption is disabled */
/* Set schedule flag if preemption is disabled | 如果禁用抢占,则设置调度标志*/
OsPercpuGet()->schedFlag |= INT_PEND_RESCH;
}
return preemptable;
}
/// 申请CPU调度锁
STATIC INLINE VOID OsCpuSchedLock(Percpu *cpu)
{
cpu->taskLockCnt++;
}
/// 释放CPU调度锁
STATIC INLINE VOID OsCpuSchedUnlock(Percpu *cpu, UINT32 intSave)
{
if (cpu->taskLockCnt > 0) {
......
......@@ -43,30 +43,30 @@ extern "C" {
#endif /* __cplusplus */
/*! \enum SortLinkType
* 因为任务和定时器都是吃CPU的,让CPU不停工作的主要就是这两宝贝.
* @brief 因为任务和定时器都是吃CPU的,让CPU不停工作的主要就是这两宝贝.
*/
typedef enum {
OS_SORT_LINK_TASK = 1, ///< 任务排序
OS_SORT_LINK_SWTMR = 2, ///< 定时器排序
OS_SORT_LINK_TASK = 1, ///< 任务
OS_SORT_LINK_SWTMR = 2, ///< 定时器
} SortLinkType;
/*! \struct SortLinkList
*
*/
typedef struct {
LOS_DL_LIST sortLinkNode; ///< 任务排序链表,注意上面挂的是一个个等待的任务
UINT64 responseTime; ///< 响应时间
LOS_DL_LIST sortLinkNode; ///< 排序链表,注意上面挂的是一个个等待被执行的任务/软件定时器
UINT64 responseTime; ///< 响应时间,注意是时间短的排在前面,见于 OsAddNode2SortLink 的实现
#ifdef LOSCFG_KERNEL_SMP
UINT32 cpuid; ///< 需要哪个CPU处理
#endif
} SortLinkList;
/*! \struct SortLinkAttribute
*
/*! \struct SortLinkAttribute
* @brief 排序链表属性
*/
typedef struct {
LOS_DL_LIST sortLink;
UINT32 nodeNum;
LOS_DL_LIST sortLink; ///< 排序链表,上面挂的任务/软件定时器
UINT32 nodeNum; ///< 链表结点数量
} SortLinkAttribute;
#define OS_SORT_LINK_INVALID_TIME ((UINT64)-1)
......
......@@ -45,79 +45,78 @@ extern "C" {
* @ingroup los_sys
* Number of milliseconds in one second.
*/
#define OS_SYS_MS_PER_SECOND 1000 //一秒多少毫秒
#define OS_SYS_MS_PER_SECOND 1000 ///< 一秒多少毫秒
/**
* @ingroup los_sys
* Number of microseconds in one second.
*/
#define OS_SYS_US_PER_SECOND 1000000 //一秒多少微秒
#define OS_SYS_US_PER_SECOND 1000000 ///< 一秒多少微秒
/**
* @ingroup los_sys
* Number of nanoseconds in one second.
*/
#define OS_SYS_NS_PER_SECOND 1000000000 //一秒多少纳秒
#define OS_SYS_NS_PER_SECOND 1000000000 ///< 一秒多少纳秒
/**
* @ingroup los_sys
* Number of microseconds in one milliseconds.
*/
#define OS_SYS_US_PER_MS 1000 //一毫秒都是微秒
#define OS_SYS_US_PER_MS 1000 ///< 一毫秒的微秒数
/**
* @ingroup los_sys
* Number of nanoseconds in one milliseconds.
*/
#define OS_SYS_NS_PER_MS 1000000 //一毫秒都是纳秒
#define OS_SYS_NS_PER_MS 1000000 ///< 一毫秒的纳秒数
/**
* @ingroup los_sys
* Number of nanoseconds in one microsecond.
*/
#define OS_SYS_NS_PER_US 1000 //一微秒都是纳秒
#define OS_SYS_NS_PER_US 1000 ///< 一微秒的纳秒数
/**
* @ingroup los_sys
* Number of cycle in one tick.
*/
#define OS_CYCLE_PER_TICK (OS_SYS_CLOCK / LOSCFG_BASE_CORE_TICK_PER_SECOND)
#define OS_CYCLE_PER_TICK (OS_SYS_CLOCK / LOSCFG_BASE_CORE_TICK_PER_SECOND) ///< 一个节拍的周期数
/**
* @ingroup los_sys
* Number of nanoseconds in one cycle.
*/
#define OS_NS_PER_CYCLE (OS_SYS_NS_PER_SECOND / OS_SYS_CLOCK)
#define OS_NS_PER_CYCLE (OS_SYS_NS_PER_SECOND / OS_SYS_CLOCK) ///< 一周期的纳秒数
/**
* @ingroup los_sys
* Number of microseconds in one tick.
*/
#define OS_US_PER_TICK (OS_SYS_US_PER_SECOND / LOSCFG_BASE_CORE_TICK_PER_SECOND)
#define OS_US_PER_TICK (OS_SYS_US_PER_SECOND / LOSCFG_BASE_CORE_TICK_PER_SECOND) ///< 一个tick的微秒数
/**
* @ingroup los_sys
* Number of nanoseconds in one tick.
*/
#define OS_NS_PER_TICK (OS_SYS_NS_PER_SECOND / LOSCFG_BASE_CORE_TICK_PER_SECOND)
#define OS_NS_PER_TICK (OS_SYS_NS_PER_SECOND / LOSCFG_BASE_CORE_TICK_PER_SECOND) ///< 一个tick的纳秒数
/**
* @ingroup los_sys
* The maximum length of name.
*/
#define OS_SYS_APPVER_NAME_MAX 64 //名字的最大长度
#define OS_SYS_APPVER_NAME_MAX 64 ///< 名字的最大长度
/**
* @ingroup los_sys
* The magic word.
*/
#define OS_SYS_MAGIC_WORD 0xAAAAAAAA //魔法数字,还记得栈顶的魔法数字是多少吗? 0xCCCCCCCC
#define OS_SYS_MAGIC_WORD 0xAAAAAAAA ///< 魔法数字,还记得栈顶的魔法数字是多少吗? 0xCCCCCCCC
/**
* @ingroup los_sys
* The initialization value of stack space.
*/
#define OS_SYS_EMPTY_STACK 0xCACACACA //栈的填充内容魔法数字
#define OS_SYS_EMPTY_STACK 0xCACACACA ///< 栈的填充内容魔法数字
/**
* @ingroup los_sys
......
......@@ -77,7 +77,7 @@ extern SPIN_LOCK_S g_taskSpin;//任务自旋锁
* Null task ID
*
*/
#define OS_TASK_ERRORID 0xFFFFFFFF
#define OS_TASK_ERRORID 0xFFFFFFFF
/**
* @ingroup los_task
......@@ -93,7 +93,7 @@ extern SPIN_LOCK_S g_taskSpin;//任务自旋锁
*
* Lowest task priority.
*/
#define OS_TASK_PRIORITY_LOWEST 31 //任务最低优先级
#define OS_TASK_PRIORITY_LOWEST 31 ///< 任务最低优先级
/**
* @ingroup los_task
......@@ -101,7 +101,7 @@ extern SPIN_LOCK_S g_taskSpin;//任务自旋锁
*
* The task is init.
*/
#define OS_TASK_STATUS_INIT 0x0001U //初始化状态
#define OS_TASK_STATUS_INIT 0x0001U ///< 初始化状态
/**
* @ingroup los_task
......@@ -109,7 +109,7 @@ extern SPIN_LOCK_S g_taskSpin;//任务自旋锁
*
* The task is ready.
*/
#define OS_TASK_STATUS_READY 0x0002U //就绪状态的任务都将插入就绪队列,注意就绪队列的本质是个双向链表
#define OS_TASK_STATUS_READY 0x0002U ///< 就绪状态的任务都将插入就绪队列,注意就绪队列的本质是个双向链表
/**
* @ingroup los_task
......@@ -117,7 +117,7 @@ extern SPIN_LOCK_S g_taskSpin;//任务自旋锁
*
* The task is running.
*/
#define OS_TASK_STATUS_RUNNING 0x0004U //运行状态
#define OS_TASK_STATUS_RUNNING 0x0004U ///< 任务状态: 运行中
/**
* @ingroup los_task
......@@ -125,7 +125,7 @@ extern SPIN_LOCK_S g_taskSpin;//任务自旋锁
*
* The task is suspended.
*/
#define OS_TASK_STATUS_SUSPENDED 0x0008U
#define OS_TASK_STATUS_SUSPENDED 0x0008U ///< 任务状态: 暂停 ,意思是任务已经开始了, 不过现在要停了
/**
* @ingroup los_task
......@@ -133,7 +133,7 @@ extern SPIN_LOCK_S g_taskSpin;//任务自旋锁
*
* The task is blocked.
*/
#define OS_TASK_STATUS_PENDING 0x0010U
#define OS_TASK_STATUS_PENDING 0x0010U ///< 任务状态: 挂起 ,意思是任务还没开始,在等待其他条件成熟
/**
* @ingroup los_task
......@@ -141,7 +141,7 @@ extern SPIN_LOCK_S g_taskSpin;//任务自旋锁
*
* The task is delayed.
*/
#define OS_TASK_STATUS_DELAY 0x0020U //延期状态
#define OS_TASK_STATUS_DELAY 0x0020U ///< 延期状态 ,见于 OsSchedDelay 延期调度
/**
* @ingroup los_task
......@@ -149,7 +149,7 @@ extern SPIN_LOCK_S g_taskSpin;//任务自旋锁
*
* The time for waiting for an event to occur expires.
*/
#define OS_TASK_STATUS_TIMEOUT 0x0040U //任务超时
#define OS_TASK_STATUS_TIMEOUT 0x0040U ///< 任务等待事件发生超时
/**
* @ingroup los_task
......@@ -157,10 +157,10 @@ extern SPIN_LOCK_S g_taskSpin;//任务自旋锁
*
* The task is pend for a period of time.
*/
#define OS_TASK_STATUS_PEND_TIME 0x0080U
#define OS_TASK_STATUS_PEND_TIME 0x0080U ///< 任务状态: 挂起
#define OS_TASK_STATUS_BLOCKED (OS_TASK_STATUS_INIT | OS_TASK_STATUS_PENDING | \
OS_TASK_STATUS_DELAY | OS_TASK_STATUS_PEND_TIME)
OS_TASK_STATUS_DELAY | OS_TASK_STATUS_PEND_TIME) ///< 任务状态: 屏蔽
/**
* @ingroup los_task
......@@ -168,7 +168,7 @@ extern SPIN_LOCK_S g_taskSpin;//任务自旋锁
*
* The task is exit.
*/
#define OS_TASK_STATUS_EXIT 0x0100U
#define OS_TASK_STATUS_EXIT 0x0100U ///< 任务状态:退出
/**
* @ingroup los_task
......@@ -176,7 +176,7 @@ extern SPIN_LOCK_S g_taskSpin;//任务自旋锁
*
* The task control block is unused.
*/
#define OS_TASK_STATUS_UNUSED 0x0200U
#define OS_TASK_STATUS_UNUSED 0x0200U ///< 任务状态:未使用
/**
* @ingroup los_task
......@@ -184,7 +184,7 @@ extern SPIN_LOCK_S g_taskSpin;//任务自旋锁
*
* The task is joinable.
*/
#define OS_TASK_FLAG_PTHREAD_JOIN 0x0400U //主task和子task连在一块不分离
#define OS_TASK_FLAG_PTHREAD_JOIN 0x0400U ///< 主task和子task连在一块不分离
/**
* @ingroup los_task
......@@ -192,15 +192,15 @@ extern SPIN_LOCK_S g_taskSpin;//任务自旋锁
*
* The task is system-level task, like idle, swtmr and etc.
*/
#define OS_TASK_FLAG_SYSTEM_TASK 0x1000U //系统任务
#define OS_TASK_FLAG_SYSTEM_TASK 0x1000U ///< 系统任务
/**
* @ingroup los_task
* Flag that indicates the task property.
*
* The task is no-delete system task, like resourceTask. //该任务是不可删除的系统任务,如资源回收任务
* The task is no-delete system task, like resourceTask.
*/
#define OS_TASK_FLAG_NO_DELETE 0x2000U
#define OS_TASK_FLAG_NO_DELETE 0x2000U ///< 该任务是不可删除的系统任务,如资源回收任务
/**
* @ingroup los_task
......@@ -208,7 +208,7 @@ extern SPIN_LOCK_S g_taskSpin;//任务自旋锁
*
* Kills the thread during process exit.
*/
#define OS_TASK_FLAG_EXIT_KILL 0x4000U //在进程退出期间一同被干掉的任务
#define OS_TASK_FLAG_EXIT_KILL 0x4000U ///< 在进程退出期间一同被干掉的任务
/**
* @ingroup los_task
......@@ -216,26 +216,26 @@ extern SPIN_LOCK_S g_taskSpin;//任务自旋锁
*
* Specifies the process creation task.
*/
#define OS_TASK_FLAG_SPECIFIES_PROCESS 0x0U //创建指定任务 例如: cat weharmony.net 实现
#define OS_TASK_FLAG_SPECIFIES_PROCESS 0x0U ///< 创建指定任务 例如: cat weharmony.net 实现
/**
* @ingroup los_task
* Boundary on which the stack size is aligned.
*
*/
#define OS_TASK_STACK_SIZE_ALIGN 16U //堆栈大小对齐的边界
#define OS_TASK_STACK_SIZE_ALIGN 16U ///< 堆栈大小对齐
/**
* @ingroup los_task
* Boundary on which the stack address is aligned.
*
*/
#define OS_TASK_STACK_ADDR_ALIGN 8U
#define OS_TASK_STACK_ADDR_ALIGN 8U ///< 堆栈地址对齐
/**
* @ingroup los_task
* Number of usable task priorities.
*/ //可用任务优先级的数量
* Number of usable task priorities. | 任务优先级数量
*/
#define OS_TSK_PRINUM (OS_TASK_PRIORITY_LOWEST - OS_TASK_PRIORITY_HIGHEST + 1)
/**
......@@ -269,9 +269,9 @@ extern SPIN_LOCK_S g_taskSpin;//任务自旋锁
* @par Dependency:
* <ul><li>los_task_pri.h: the header file that contains the API declaration.</li></ul>
* @see
*/
*/ ///通过pendList取出TCB,用于挂入链表节点时使用 pendList的情况
#define OS_TCB_FROM_PENDLIST(ptr) LOS_DL_LIST_ENTRY(ptr, LosTaskCB, pendList)
//通过pendList取出TCB,用于挂入链表节点时使用 pendList的情况
/**
* @ingroup los_task
* @brief Obtain the pointer to a task control block.
......@@ -286,19 +286,19 @@ extern SPIN_LOCK_S g_taskSpin;//任务自旋锁
* @par Dependency:
* <ul><li>los_task_pri.h: the header file that contains the API declaration.</li></ul>
* @see
*/
*/ ///通过任务ID找到任务实体
#define OS_TCB_FROM_TID(taskID) (((LosTaskCB *)g_taskCBArray) + (taskID))
//通过Tid找到TCB
#ifndef LOSCFG_STACK_POINT_ALIGN_SIZE
#define LOSCFG_STACK_POINT_ALIGN_SIZE (sizeof(UINTPTR) * 2)
#endif
#define OS_TASK_RESOURCE_STATIC_SIZE 0x1000 //4K
#define OS_TASK_RESOURCE_FREE_PRIORITY 5 //回收资源任务的优先级
#define OS_RESOURCE_EVENT_MASK 0xFF //资源事件的掩码
#define OS_RESOURCE_EVENT_OOM 0x02 //内存溢出事件
#define OS_RESOURCE_EVENT_FREE 0x04 //资源释放事件
#define OS_TCB_NAME_LEN 32
#define OS_TASK_RESOURCE_STATIC_SIZE 0x1000 ///< 4K
#define OS_TASK_RESOURCE_FREE_PRIORITY 5 ///< 回收资源任务的优先级
#define OS_RESOURCE_EVENT_MASK 0xFF ///< 资源事件的掩码
#define OS_RESOURCE_EVENT_OOM 0x02 ///< 内存溢出事件
#define OS_RESOURCE_EVENT_FREE 0x04 ///< 资源释放事件
#define OS_TCB_NAME_LEN 32 ///< 任务名称长度上限
typedef struct {
VOID *stackPointer; /**< Task stack pointer | 内核栈指针位置(SP) */
......@@ -311,7 +311,7 @@ typedef struct {
UINT32 initTimeSlice; /**< Task init time slice | 任务初始的时间片 */
INT32 timeSlice; /**< Task remaining time slice | 任务剩余时间片 */
UINT32 waitTimes; /**< Task delay time, tick number | 设置任务调度延期时间 */
SortLinkList sortList; /**< Task sortlink node | 任务排序链表节点 */
SortLinkList sortList; /**< Task sortlink node | 跟CPU捆绑的任务排序链表节点,上面挂的是就绪队列的下一个阶段,进入CPU要执行的任务队列 */
UINT32 stackSize; /**< Task stack size | 内核态栈大小,内存来自内核空间 */
UINTPTR topOfStack; /**< Task stack top | 内核态栈顶 bottom = top + size */
UINT32 taskID; /**< Task ID | 任务ID,任务池本质是一个大数组,ID就是数组的索引,默认 < 128 */
......@@ -365,13 +365,14 @@ typedef struct {
UINTPTR fp; ///< fp寄存器
#endif
} LosTaskCB;
//LosTask结构体是给外部使用的
///< LosTask结构体是给外部使用的
typedef struct {
LosTaskCB *runTask;
LosTaskCB *newTask;
} LosTask;
struct ProcessSignalInfo {//进程信号描述符
///< 进程信号描述符
struct ProcessSignalInfo {
siginfo_t *sigInfo; /**< Signal to be dispatched | 要发送的信号*/
LosTaskCB *defaultTcb; /**< Default TCB | 默认task,默认接收信号的任务. */
LosTaskCB *unblockedTcb; /**< The signal unblock on this TCB | 信号在此TCB上解除阻塞 */
......@@ -405,27 +406,27 @@ typedef struct {//时间片结构体,任务轮询
UINT16 time; /**< Expiration time point | 过期时间点*/
UINT16 timeout; /**< Expiration duration | 有效期*/
} OsTaskRobin;
//获取当前CPU core运行的任务
/// 获取当前CPU core运行的任务
STATIC INLINE LosTaskCB *OsCurrTaskGet(VOID)
{
return (LosTaskCB *)ArchCurrTaskGet();
}
///告诉协处理器当前任务使用范围为内核空间
/// 告诉协处理器当前任务使用范围为内核空间
STATIC INLINE VOID OsCurrTaskSet(LosTaskCB *task)
{
ArchCurrTaskSet(task);
}
///告诉协处理器当前任务使用范围为 用户空间
/// 告诉协处理器当前任务使用范围为 用户空间
STATIC INLINE VOID OsCurrUserTaskSet(UINTPTR thread)
{
ArchCurrUserTaskSet(thread);
}
///通过任务ID获取任务实体,task由任务池分配,本质是个数组,彼此都挨在一块
/// 通过任务ID获取任务实体,task由任务池分配,本质是个数组,彼此都挨在一块
STATIC INLINE LosTaskCB *OsGetTaskCB(UINT32 taskID)
{
return OS_TCB_FROM_TID(taskID);
}
///任务是否在使用
/// 任务是否在使用
STATIC INLINE BOOL OsTaskIsUnused(const LosTaskCB *taskCB)
{
if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {//在freelist中的任务都是 OS_TASK_STATUS_UNUSED 状态
......@@ -434,7 +435,7 @@ STATIC INLINE BOOL OsTaskIsUnused(const LosTaskCB *taskCB)
return FALSE;
}
///任务是否在运行
/// 任务是否在运行
STATIC INLINE BOOL OsTaskIsRunning(const LosTaskCB *taskCB)
{
if (taskCB->taskStatus & OS_TASK_STATUS_RUNNING) {//一个CPU core 只能有一个 OS_TASK_STATUS_RUNNING task
......@@ -443,7 +444,7 @@ STATIC INLINE BOOL OsTaskIsRunning(const LosTaskCB *taskCB)
return FALSE;
}
///任务是否不再活动
/// 任务是否不再活动
STATIC INLINE BOOL OsTaskIsInactive(const LosTaskCB *taskCB)
{
if (taskCB->taskStatus & (OS_TASK_STATUS_UNUSED | OS_TASK_STATUS_INIT | OS_TASK_STATUS_EXIT)) {//三个标签有一个代表不在活动
......@@ -452,7 +453,7 @@ STATIC INLINE BOOL OsTaskIsInactive(const LosTaskCB *taskCB)
return FALSE;
}
/// 任务是否挂起
STATIC INLINE BOOL OsTaskIsPending(const LosTaskCB *taskCB)
{
if (taskCB->taskStatus & OS_TASK_STATUS_PENDING) {
......@@ -461,7 +462,7 @@ STATIC INLINE BOOL OsTaskIsPending(const LosTaskCB *taskCB)
return FALSE;
}
/// 任务是否被干掉
STATIC INLINE BOOL OsTaskIsKilled(const LosTaskCB *taskCB)
{
if (taskCB->taskStatus & OS_TASK_FLAG_EXIT_KILL) {
......@@ -489,7 +490,7 @@ STATIC INLINE BOOL OsTaskIsKilled(const LosTaskCB *taskCB)
#define OS_TASK_WAIT_EVENT (OS_TASK_WAIT_FUTEX + 1) ///< 任务等待事件发生
#define OS_TASK_WAIT_COMPLETE (OS_TASK_WAIT_EVENT + 1) ///< 任务等待完成
//设置事件阻塞掩码,即设置任务的等待事件.
/// 设置事件阻塞掩码,即设置任务的等待事件.
STATIC INLINE VOID OsTaskWaitSetPendMask(UINT16 mask, UINTPTR lockID, UINT32 timeout)
{
LosTaskCB *runTask = OsCurrTaskGet();
......@@ -498,7 +499,7 @@ STATIC INLINE VOID OsTaskWaitSetPendMask(UINT16 mask, UINTPTR lockID, UINT32 tim
(VOID)timeout;
}
//清除事件阻塞掩码,即任务不再等待任何事件.
/// 清除事件阻塞掩码,即任务不再等待任何事件.
STATIC INLINE VOID OsTaskWakeClearPendMask(LosTaskCB *resumeTask)
{
resumeTask->waitID = 0;
......
......@@ -633,17 +633,17 @@ VOID OsSchedTaskEnQueue(LosTaskCB *taskCB)
#endif
OsSchedEnTaskQueue(taskCB, processCB);
}
/// 任务退出
VOID OsSchedTaskExit(LosTaskCB *taskCB)
{
LosProcessCB *processCB = OS_PCB_FROM_PID(taskCB->processID);
if (taskCB->taskStatus & OS_TASK_STATUS_READY) {
OsSchedTaskDeQueue(taskCB);
processCB->processStatus &= ~OS_PROCESS_STATUS_PENDING;
} else if (taskCB->taskStatus & OS_TASK_STATUS_PENDING) {
LOS_ListDelete(&taskCB->pendList);
taskCB->taskStatus &= ~OS_TASK_STATUS_PENDING;
if (taskCB->taskStatus & OS_TASK_STATUS_READY) {//就绪状态
OsSchedTaskDeQueue(taskCB);//从就绪队列中删除
processCB->processStatus &= ~OS_PROCESS_STATUS_PENDING;//进程贴上非挂起标签
} else if (taskCB->taskStatus & OS_TASK_STATUS_PENDING) { //挂起状态
LOS_ListDelete(&taskCB->pendList); //从任务挂起链表中摘除
taskCB->taskStatus &= ~OS_TASK_STATUS_PENDING;////任务贴上非挂起标签
}
if (taskCB->taskStatus & (OS_TASK_STATUS_DELAY | OS_TASK_STATUS_PEND_TIME)) {
......
......@@ -35,96 +35,105 @@
#include "los_percpu_pri.h"
#include "los_sched_pri.h"
#include "los_mp.h"
/// 排序链表初始化
UINT32 OsSortLinkInit(SortLinkAttribute *sortLinkHeader)
{
LOS_ListInit(&sortLinkHeader->sortLink);
sortLinkHeader->nodeNum = 0;
LOS_ListInit(&sortLinkHeader->sortLink);//初始化双向链表
sortLinkHeader->nodeNum = 0;//nodeNum背后的含义是记录需要CPU工作的数量
return LOS_OK;
}
/*!
* @brief OsAddNode2SortLink 向链表中插入结点,并按时间顺序排列
*
* @param sortLinkHeader 被插入的链表
* @param sortList 要插入的结点
* @return
*
* @see
*/
STATIC INLINE VOID OsAddNode2SortLink(SortLinkAttribute *sortLinkHeader, SortLinkList *sortList)
{
LOS_DL_LIST *head = (LOS_DL_LIST *)&sortLinkHeader->sortLink;
LOS_DL_LIST *head = (LOS_DL_LIST *)&sortLinkHeader->sortLink; //获取双向链表
if (LOS_ListEmpty(head)) {
LOS_ListHeadInsert(head, &sortList->sortLinkNode);
sortLinkHeader->nodeNum++;
if (LOS_ListEmpty(head)) { //空链表,直接插入
LOS_ListHeadInsert(head, &sortList->sortLinkNode);//插入结点
sortLinkHeader->nodeNum++;//CPU的工作量增加了
return;
}
//链表不为空时,插入分三种情况, responseTime 大于,等于,小于的处理
SortLinkList *listSorted = LOS_DL_LIST_ENTRY(head->pstNext, SortLinkList, sortLinkNode);
if (listSorted->responseTime > sortList->responseTime) {
LOS_ListAdd(head, &sortList->sortLinkNode);
sortLinkHeader->nodeNum++;
return;
} else if (listSorted->responseTime == sortList->responseTime) {
LOS_ListAdd(head->pstNext, &sortList->sortLinkNode);
if (listSorted->responseTime > sortList->responseTime) {//如果要插入的节点 responseTime 最小
LOS_ListAdd(head, &sortList->sortLinkNode);//能跑进来说明是最小的,直接插入到第一的位置
sortLinkHeader->nodeNum++;//CPU的工作量增加了
return;//直接返回了
} else if (listSorted->responseTime == sortList->responseTime) {//相等的情况
LOS_ListAdd(head->pstNext, &sortList->sortLinkNode);//插到第二的位置
sortLinkHeader->nodeNum++;
return;
}
LOS_DL_LIST *prevNode = head->pstPrev;
do {
listSorted = LOS_DL_LIST_ENTRY(prevNode, SortLinkList, sortLinkNode);
if (listSorted->responseTime <= sortList->responseTime) {
//处理大于链表中第一个responseTime的情况,需要遍历链表
LOS_DL_LIST *prevNode = head->pstPrev;//注意这里用的前一个结点,也就是说前一个结点中的responseTime 是最大的
do { // @note_good 这里写的有点妙,也是双向链表的魅力所在
listSorted = LOS_DL_LIST_ENTRY(prevNode, SortLinkList, sortLinkNode);//一个个遍历,先比大的再比小的
if (listSorted->responseTime <= sortList->responseTime) {//如果时间比你小,就插到后面
LOS_ListAdd(prevNode, &sortList->sortLinkNode);
sortLinkHeader->nodeNum++;
break;
}
prevNode = prevNode->pstPrev;
} while (1);
prevNode = prevNode->pstPrev;//再拿上一个更小的responseTime进行比较
} while (1);//死循环
}
/// 从排序链表上摘除指定节点
VOID OsDeleteNodeSortLink(SortLinkAttribute *sortLinkHeader, SortLinkList *sortList)
{
LOS_ListDelete(&sortList->sortLinkNode);
SET_SORTLIST_VALUE(sortList, OS_SORT_LINK_INVALID_TIME);
sortLinkHeader->nodeNum--;
LOS_ListDelete(&sortList->sortLinkNode);//摘除工作量
SET_SORTLIST_VALUE(sortList, OS_SORT_LINK_INVALID_TIME);//重置响应时间
sortLinkHeader->nodeNum--;//cpu的工作量减少一份
}
/// 获取下一个结点的过期时间
STATIC INLINE UINT64 OsGetSortLinkNextExpireTime(SortLinkAttribute *sortHeader, UINT64 startTime)
{
LOS_DL_LIST *head = &sortHeader->sortLink;
LOS_DL_LIST *list = head->pstNext;
if (LOS_ListEmpty(head)) {
if (LOS_ListEmpty(head)) {//链表为空
return OS_SCHED_MAX_RESPONSE_TIME - OS_TICK_RESPONSE_PRECISION;
}
SortLinkList *listSorted = LOS_DL_LIST_ENTRY(list, SortLinkList, sortLinkNode);
if (listSorted->responseTime <= (startTime + OS_TICK_RESPONSE_PRECISION)) {
SortLinkList *listSorted = LOS_DL_LIST_ENTRY(list, SortLinkList, sortLinkNode);//获取结点实体
if (listSorted->responseTime <= (startTime + OS_TICK_RESPONSE_PRECISION)) { //没看明白 @note_thinking
return startTime + OS_TICK_RESPONSE_PRECISION;
}
return listSorted->responseTime;
}
/// 根据函数的具体实现,这个函数应该是找出最空闲的CPU, 函数的实现有待优化, @note_thinking
STATIC Percpu *OsFindIdleCpu(UINT16 *idleCpuID)
{
Percpu *idleCpu = OsPercpuGetByID(0);
Percpu *idleCpu = OsPercpuGetByID(0); //获取0号CPU,0号CPU也可称主核
*idleCpuID = 0;
#ifdef LOSCFG_KERNEL_SMP
#ifdef LOSCFG_KERNEL_SMP //多核情况下
UINT16 cpuID = 1;
UINT32 nodeNum = idleCpu->taskSortLink.nodeNum + idleCpu->swtmrSortLink.nodeNum;
UINT32 nodeNum = idleCpu->taskSortLink.nodeNum + idleCpu->swtmrSortLink.nodeNum; //获取还未跑完的工作数量
//cpu执行两种工作: 1.普通任务 2.软件定时器
do {
Percpu *cpu = OsPercpuGetByID(cpuID);
UINT32 temp = cpu->taskSortLink.nodeNum + cpu->swtmrSortLink.nodeNum;
if (nodeNum > temp) {
idleCpu = cpu;
*idleCpuID = cpuID;
Percpu *cpu = OsPercpuGetByID(cpuID); //一个个cpu遍历
UINT32 temp = cpu->taskSortLink.nodeNum + cpu->swtmrSortLink.nodeNum;//获取cpu的工作量
if (nodeNum > temp) {//对工作量比较
idleCpu = cpu;//取工作量最小的cpu实体
*idleCpuID = cpuID;//获取cpu id
}
cpuID++;
cpuID++;//下一个cpu id
} while (cpuID < LOSCFG_KERNEL_CORE_NUM);
#endif
return idleCpu;
}
/// 向cpu的排序链表上添加指定节点
VOID OsAdd2SortLink(SortLinkList *node, UINT64 startTime, UINT32 waitTicks, SortLinkType type)
{
UINT32 intSave;
......@@ -133,51 +142,51 @@ VOID OsAdd2SortLink(SortLinkList *node, UINT64 startTime, UINT32 waitTicks, Sort
SPIN_LOCK_S *spinLock = NULL;
UINT16 idleCpu;
if (OS_SCHEDULER_ACTIVE) {
cpu = OsFindIdleCpu(&idleCpu);
if (OS_SCHEDULER_ACTIVE) {//当前CPU正在调度
cpu = OsFindIdleCpu(&idleCpu);//找一个最空闲的CPU
} else {
idleCpu = ArchCurrCpuid();
idleCpu = ArchCurrCpuid();//使用当前cpu
cpu = OsPercpuGet();
}
if (type == OS_SORT_LINK_TASK) {
sortLinkHeader = &cpu->taskSortLink;
if (type == OS_SORT_LINK_TASK) {//任务类型
sortLinkHeader = &cpu->taskSortLink; //获取任务链表
spinLock = &cpu->taskSortLinkSpin;
} else if (type == OS_SORT_LINK_SWTMR) {
sortLinkHeader = &cpu->swtmrSortLink;
} else if (type == OS_SORT_LINK_SWTMR) {//软件定时器类型
sortLinkHeader = &cpu->swtmrSortLink;//获取软件定时器链表
spinLock = &cpu->swtmrSortLinkSpin;
} else {
LOS_Panic("Sort link type error : %u\n", type);
}
LOS_SpinLockSave(spinLock, &intSave);
SET_SORTLIST_VALUE(node, startTime + (UINT64)waitTicks * OS_CYCLE_PER_TICK);
OsAddNode2SortLink(sortLinkHeader, node);
SET_SORTLIST_VALUE(node, startTime + (UINT64)waitTicks * OS_CYCLE_PER_TICK);//设置节点响应时间
OsAddNode2SortLink(sortLinkHeader, node);//插入节点
#ifdef LOSCFG_KERNEL_SMP
node->cpuid = idleCpu;
if (idleCpu != ArchCurrCpuid()) {
LOS_MpSchedule(CPUID_TO_AFFI_MASK(idleCpu));
if (idleCpu != ArchCurrCpuid()) { //如果插入的链表不是当前CPU的链表
LOS_MpSchedule(CPUID_TO_AFFI_MASK(idleCpu));//核间中断,对该CPU发生一次调度申请
}
#endif
LOS_SpinUnlockRestore(spinLock, intSave);
}
/// 从cpu的排序链表上摘除指定节点
VOID OsDeleteSortLink(SortLinkList *node, SortLinkType type)
{
UINT32 intSave;
#ifdef LOSCFG_KERNEL_SMP
Percpu *cpu = OsPercpuGetByID(node->cpuid);
Percpu *cpu = OsPercpuGetByID(node->cpuid);//获取CPU
#else
Percpu *cpu = OsPercpuGetByID(0);
#endif
SPIN_LOCK_S *spinLock = NULL;
SortLinkAttribute *sortLinkHeader = NULL;
if (type == OS_SORT_LINK_TASK) {
sortLinkHeader = &cpu->taskSortLink;
if (type == OS_SORT_LINK_TASK) {//当为任务时
sortLinkHeader = &cpu->taskSortLink;//获取该CPU的任务链表
spinLock = &cpu->taskSortLinkSpin;
} else if (type == OS_SORT_LINK_SWTMR) {
sortLinkHeader = &cpu->swtmrSortLink;
sortLinkHeader = &cpu->swtmrSortLink;//获取该CPU的定时器链表
spinLock = &cpu->swtmrSortLinkSpin;
} else {
LOS_Panic("Sort link type error : %u\n", type);
......@@ -185,29 +194,45 @@ VOID OsDeleteSortLink(SortLinkList *node, SortLinkType type)
LOS_SpinLockSave(spinLock, &intSave);
if (node->responseTime != OS_SORT_LINK_INVALID_TIME) {
OsDeleteNodeSortLink(sortLinkHeader, node);
OsDeleteNodeSortLink(sortLinkHeader, node);//从CPU的执行链表上摘除
}
LOS_SpinUnlockRestore(spinLock, intSave);
}
/*!
* @brief OsGetNextExpireTime 获取下一个超时时间
*
* @param startTime
* @return
*
* @see
*/
UINT64 OsGetNextExpireTime(UINT64 startTime)
{
UINT32 intSave;
Percpu *cpu = OsPercpuGet();
Percpu *cpu = OsPercpuGet();//获取当前CPU
SortLinkAttribute *taskHeader = &cpu->taskSortLink;
SortLinkAttribute *swtmrHeader = &cpu->swtmrSortLink;
LOS_SpinLockSave(&cpu->taskSortLinkSpin, &intSave);
UINT64 taskExpirTime = OsGetSortLinkNextExpireTime(taskHeader, startTime);
UINT64 taskExpirTime = OsGetSortLinkNextExpireTime(taskHeader, startTime);//拿到下一个过期时间,注意此处拿到的一定是最短的时间
LOS_SpinUnlockRestore(&cpu->taskSortLinkSpin, intSave);
LOS_SpinLockSave(&cpu->swtmrSortLinkSpin, &intSave);
UINT64 swtmrExpirTime = OsGetSortLinkNextExpireTime(swtmrHeader, startTime);
LOS_SpinUnlockRestore(&cpu->swtmrSortLinkSpin, intSave);
return (taskExpirTime < swtmrExpirTime) ? taskExpirTime : swtmrExpirTime;
return (taskExpirTime < swtmrExpirTime) ? taskExpirTime : swtmrExpirTime;//比较返回更短的那个.
}
/*!
* @brief OsSortLinkGetTargetExpireTime
* 返回离触发目标时间的tick数
* @param targetSortList
* @return
*
* @see
*/
UINT32 OsSortLinkGetTargetExpireTime(const SortLinkList *targetSortList)
{
UINT64 currTimes = OsGetCurrSchedTimeCycle();
......@@ -215,7 +240,7 @@ UINT32 OsSortLinkGetTargetExpireTime(const SortLinkList *targetSortList)
return 0;
}
return (UINT32)(targetSortList->responseTime - currTimes) / OS_CYCLE_PER_TICK;
return (UINT32)(targetSortList->responseTime - currTimes) / OS_CYCLE_PER_TICK;//响应时间减去当前时间置算出剩余tick数
}
UINT32 OsSortLinkGetNextExpireTime(const SortLinkAttribute *sortLinkHeader)
......
git add -A
git commit -m ' 因同步官源,代码覆盖,部分模块需重新注解
git commit -m ' CPU的工作量是如何分配的, 读懂对 SortLinkList 的注解即可
百万汉字注解 + 百篇博客分析 => 挖透鸿蒙内核源码
博客输出站点(国内):http://weharmonyos.com
博客输出站点(国外):https://weharmony.github.io
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册