完善任务在用户态运行的注解

    百万汉字注解 + 百篇博客分析 => 挖透鸿蒙内核源码
    https://my.oschina.net/weharmony
上级 fbfec390
......@@ -154,7 +154,7 @@ LITE_OS_SEC_BSS LosTaskCB *g_taskCBArray;//任务池 128个
LITE_OS_SEC_BSS LOS_DL_LIST g_losFreeTask;//空闲任务链表
LITE_OS_SEC_BSS LOS_DL_LIST g_taskRecyleList;//回收任务链表
LITE_OS_SEC_BSS UINT32 g_taskMaxNum;//任务最大个数
LITE_OS_SEC_BSS UINT32 g_taskScheduled; /* one bit for each cores *///任务调度器,每个CPU都有对应位
LITE_OS_SEC_BSS UINT32 g_taskScheduled; /* one bit for each cores *///任务调度器,每个CPU都有对应位
LITE_OS_SEC_BSS EVENT_CB_S g_resourceEvent;//资源的事件
/* spinlock for task module, only available on SMP mode */
LITE_OS_SEC_BSS SPIN_LOCK_INIT(g_taskSpin);
......@@ -961,7 +961,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreate(UINT32 *taskID, TSK_INIT_PARAM_S *in
/* in case created task not running on this core,
schedule or not depends on other schedulers status. */
LOS_MpSchedule(OS_MP_CPU_ALL);//如果创建的任务没有在这个核心上运行,是否调度取决于其他调度程序的状态。
LOS_MpSchedule(OS_MP_CPU_ALL);//向所有cpu发送调度
if (OS_SCHEDULER_ACTIVE) {//当前CPU核处于可调度状态
LOS_Schedule();//发起调度
}
......@@ -998,8 +998,8 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskResume(UINT32 taskID)
taskCB->taskStatus &= ~OS_TASK_STATUS_SUSPEND;
if (!(taskCB->taskStatus & OS_CHECK_TASK_BLOCK)) {
OS_TASK_SCHED_QUEUE_ENQUEUE(taskCB, OS_PROCESS_STATUS_PEND);
if (OS_SCHEDULER_ACTIVE) {
OS_TASK_SCHED_QUEUE_ENQUEUE(taskCB, OS_PROCESS_STATUS_PEND);//去掉任务阻塞标签,加入就绪队列
if (OS_SCHEDULER_ACTIVE) {//当前CPU是否可调度
needSched = TRUE;
}
}
......@@ -1007,7 +1007,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskResume(UINT32 taskID)
SCHEDULER_UNLOCK(intSave);
if (needSched) {//需要调度
LOS_MpSchedule(OS_MP_CPU_ALL);//
LOS_MpSchedule(OS_MP_CPU_ALL);
LOS_Schedule();
}
......@@ -1631,7 +1631,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskCpuAffiSet(UINT32 taskID, UINT16 cpuAffiMa
}
taskCB->cpuAffiMask = cpuAffiMask;//参数set给tcb
currCpuMask = CPUID_TO_AFFI_MASK(taskCB->currCpu);
currCpuMask = CPUID_TO_AFFI_MASK(taskCB->currCpu);//获取掩码位 0100 代表 2号CPU
if (!(currCpuMask & cpuAffiMask)) {
needSched = TRUE;//需要调度
taskCB->signal = SIGNAL_AFFI;//设置信号
......@@ -1639,7 +1639,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskCpuAffiSet(UINT32 taskID, UINT16 cpuAffiMa
SCHEDULER_UNLOCK(intSave);
if (needSched && OS_SCHEDULER_ACTIVE) {
LOS_MpSchedule(currCpuMask);//发送信号调度信号给currCpuMask 1位上的CPU
LOS_MpSchedule(currCpuMask);//发送信号调度信号给目标CPU
LOS_Schedule();//申请调度
}
#endif
......@@ -1647,7 +1647,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskCpuAffiSet(UINT32 taskID, UINT16 cpuAffiMa
(VOID)cpuAffiMask;
return LOS_OK;
}
//查询任务绑在哪个CPU上
//查询任务绑在哪个CPU上
LITE_OS_SEC_TEXT_MINOR UINT16 LOS_TaskCpuAffiGet(UINT32 taskID)
{
#if (LOSCFG_KERNEL_SMP == YES)
......@@ -1660,20 +1660,20 @@ LITE_OS_SEC_TEXT_MINOR UINT16 LOS_TaskCpuAffiGet(UINT32 taskID)
return INVALID_CPU_AFFI_MASK;
}
taskCB = OS_TCB_FROM_TID(taskID);
taskCB = OS_TCB_FROM_TID(taskID);//获取任务实体
SCHEDULER_LOCK(intSave);
if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) {
if (taskCB->taskStatus & OS_TASK_STATUS_UNUSED) { //任务必须在使用
SCHEDULER_UNLOCK(intSave);
return INVALID_CPU_AFFI_MASK;
}
cpuAffiMask = taskCB->cpuAffiMask;
cpuAffiMask = taskCB->cpuAffiMask; //获取亲和力掩码
SCHEDULER_UNLOCK(intSave);
return cpuAffiMask;
#else
(VOID)taskID;
return 1;
return 1;//单核情况直接返回1 ,0号cpu对应0x01
#endif
}
......@@ -1841,7 +1841,7 @@ LITE_OS_SEC_TEXT VOID OsTaskExitGroup(UINT32 status)
#endif
SCHEDULER_UNLOCK(intSave);
LOS_ASSERT(processCB->threadNumber == 1);//这一趟下来,断言进程只有一个正在活动的任务了
LOS_ASSERT(processCB->threadNumber == 1);//这一趟下来,进程只有一个正在活动的任务
return;
}
//任务退群并销毁,进入任务的回收链表之后再进入空闲链表,等着再次被分配使用.
......@@ -1909,18 +1909,18 @@ LITE_OS_SEC_TEXT_INIT STATIC UINT32 OsCreateUserTaskParamCheck(UINT32 processID,
}
userParam = &param->userParam;
if ((processID == OS_INVALID_VALUE) && !LOS_IsUserAddress(userParam->userArea)) {
if ((processID == OS_INVALID_VALUE) && !LOS_IsUserAddress(userParam->userArea)) {//堆地址必须在用户空间
return OS_INVALID_VALUE;
}
if (!LOS_IsUserAddress((UINTPTR)param->pfnTaskEntry)) {
if (!LOS_IsUserAddress((UINTPTR)param->pfnTaskEntry)) {//入口函数必须在用户空间
return OS_INVALID_VALUE;
}
//堆栈必须在用户空间
if ((!userParam->userMapSize) || !LOS_IsUserAddressRange(userParam->userMapBase, userParam->userMapSize)) {
return OS_INVALID_VALUE;
}
//检查堆,栈范围
if (userParam->userArea &&
((userParam->userSP <= userParam->userMapBase) ||
(userParam->userSP > (userParam->userMapBase + userParam->userMapSize)))) {
......@@ -1937,13 +1937,13 @@ LITE_OS_SEC_TEXT_INIT INT32 OsCreateUserTask(UINT32 processID, TSK_INIT_PARAM_S
UINT32 ret;
UINT32 intSave;
ret = OsCreateUserTaskParamCheck(processID, initParam);
ret = OsCreateUserTaskParamCheck(processID, initParam);//检查参数,堆栈,入口地址必须在用户空间
if (ret != LOS_OK) {
return ret;
}
initParam->uwStackSize = OS_USER_TASK_SYSCALL_SATCK_SIZE;//设置任务栈大小,这里用了用户态下系统调用的栈大小(12K)
initParam->usTaskPrio = OS_TASK_PRIORITY_LOWEST;//设置默认优先
//这里可看出一个任务有两个栈,内核态栈(内核指定栈大小)和用户态栈(用户指定栈大小)
initParam->uwStackSize = OS_USER_TASK_SYSCALL_SATCK_SIZE;//设置内核栈大小,即处理系统调用的栈(12K)
initParam->usTaskPrio = OS_TASK_PRIORITY_LOWEST;//设置最低优先级 31
initParam->policy = LOS_SCHED_RR;//调度方式为抢占式,注意鸿蒙不仅仅只支持抢占式调度方式
if (processID == OS_INVALID_VALUE) {//外面没指定进程ID的处理
SCHEDULER_LOCK(intSave);
......@@ -1953,7 +1953,7 @@ LITE_OS_SEC_TEXT_INIT INT32 OsCreateUserTask(UINT32 processID, TSK_INIT_PARAM_S
SCHEDULER_UNLOCK(intSave);
} else {//进程已经创建
processCB = OS_PCB_FROM_PID(processID);//通过ID拿到进程PCB
if (!(processCB->processStatus & (OS_PROCESS_STATUS_INIT | OS_PROCESS_STATUS_RUNNING))) {//进程状态有初始和正在运行两个标签
if (!(processCB->processStatus & (OS_PROCESS_STATUS_INIT | OS_PROCESS_STATUS_RUNNING))) {//进程未初始化和未正在运行
return OS_INVALID_VALUE;//@note_why 为什么这两种情况下会创建任务失败
}
initParam->processID = processID;//进程ID赋值
......
......@@ -42,20 +42,20 @@ extern "C" {
#endif /* __cplusplus */
extern UINT32 g_taskScheduled;
//调度标志,一个位代表一个CPU核,这么看鸿蒙最大支持32核,例如:4个CPU,每个4核 就一共16个核,足够了.该标志用于在调用OSStartToRun之前防止内核调度
//设置调度标识位,对应位设置为1,一个位代表一个CPU核,此标志用于在OSStartRun之前阻止内核调度
/*
* Schedule flag, one bit represents one core.
* This flag is used to prevent kernel scheduling before OSStartToRun.
*/
#define OS_SCHEDULER_SET(cpuid) do { \
g_taskScheduled |= (1U << (cpuid)); \
} while (0);//对应位设置为1
} while (0);
//清楚调度标识位,对应位设置为0
#define OS_SCHEDULER_CLR(cpuid) do { \
g_taskScheduled &= ~(1U << (cpuid)); \
} while (0);//对应位设置为0
} while (0);
#define OS_SCHEDULER_ACTIVE (g_taskScheduled & (1U << ArchCurrCpuid()))//代表位上是否为1
#define OS_SCHEDULER_ACTIVE (g_taskScheduled & (1U << ArchCurrCpuid()))//用于判断当前cpu是否可调度
typedef enum {
INT_NO_RESCH = 0, /* no needs to schedule */
......
......@@ -294,7 +294,7 @@ extern SPIN_LOCK_S g_taskSpin;//任务自旋锁
#define OS_TCB_NAME_LEN 32
typedef struct {
VOID *stackPointer; /**< Task stack pointer */ //内核栈指针位置,内核栈默认保存了初始的上下文信息.
VOID *stackPointer; /**< Task stack pointer */ //栈指针SP,任务当前执行栈的位置(用户栈和内核栈切换)
UINT16 taskStatus; /**< Task status */ //各种状态标签,可以拥有多种标签,按位标识
UINT16 priority; /**< Task priority */ //任务优先级[0:31],默认是31级
UINT16 policy; //任务的调度方式(三种 .. LOS_SCHED_RR )
......@@ -312,7 +312,7 @@ typedef struct {
LOS_DL_LIST pendList; /**< Task pend node */ //如果任务阻塞时就通过它挂到各种阻塞情况的链表上,比如OsTaskWait时
LOS_DL_LIST threadList; /**< thread list */ //挂到所属进程的线程链表上
SortLinkList sortList; /**< Task sortlink node */ //task wait,delay时挂到cpu core的taskSortLink链表上
UINT32 eventMask; /**< Event mask */ //对哪些事件进行屏蔽
UINT32 eventMask; /**< Event mask */ //任务对哪些事件进行屏蔽
UINT32 eventMode; /**< Event mode */ //事件三种模式(LOS_WAITMODE_AND,LOS_WAITMODE_OR,LOS_WAITMODE_CLR)
UINT32 priBitMap; /**< BitMap for recording the change of task priority, //任务在执行过程中优先级会经常变化,这个变量用来记录所有曾经变化
the priority can not be greater than 31 */ //过的优先级,例如 ..01001011 曾经有过 0,1,3,6 优先级
......@@ -334,9 +334,9 @@ typedef struct {
SchedStat schedStat; /**< Schedule statistics */ //调度统计
#endif
#endif
UINTPTR userArea; //用户空间,由运行时划定,根据运行态不同而不同
UINTPTR userMapBase; //用户态栈基地址,内存来自用户空间,和topOfStack有本质的区别.
UINT32 userMapSize; /**< user thread stack size ,real size : userMapSize + USER_STACK_MIN_SIZE */
UINTPTR userArea; //用户空间的堆区开始位置
UINTPTR userMapBase; //用户空间的栈顶位置,内存来自用户空间,和topOfStack有本质的区别.
UINT32 userMapSize; /**< user thread stack size ,real size : userMapSize + USER_STACK_MIN_SIZE *///用户栈大小
UINT32 processID; /**< Which belong process *///所属进程ID
FutexNode futex; //实现快锁功能
LOS_DL_LIST joinList; /**< join list */ //联结链表,允许任务之间相互释放彼此
......@@ -456,9 +456,8 @@ STATIC INLINE BOOL OsTaskIsInactive(const LosTaskCB *taskCB)
#define OS_TASK_PRI_QUEUE_DEQUEUE(processCB, taskCB) \
OsPriQueueDequeue((processCB)->threadPriQueueList, &((processCB)->threadScheduleMap), &((taskCB)->pendList))
//入和出 任务调度就绪队列
#define OS_TASK_SCHED_QUEUE_ENQUEUE(taskCB, status) OsTaskSchedQueueEnqueue(taskCB, status)
#define OS_TASK_SCHED_QUEUE_DEQUEUE(taskCB, status) OsTaskSchedQueueDequeue(taskCB, status)
#define OS_TASK_SCHED_QUEUE_ENQUEUE(taskCB, status) OsTaskSchedQueueEnqueue(taskCB, status) //加入任务调度就绪队列
#define OS_TASK_SCHED_QUEUE_DEQUEUE(taskCB, status) OsTaskSchedQueueDequeue(taskCB, status) //退出任务调度就绪队列
//入和出 进程的就绪队列 ,还提供了从头部入队列的方法
#define OS_PROCESS_PRI_QUEUE_ENQUEUE(processCB) \
OsPriQueueEnqueue(g_priQueueList, &g_priQueueBitmap, &((processCB)->pendList), (processCB)->priority)
......
......@@ -162,7 +162,7 @@ LITE_OS_SEC_TEXT_INIT VOID OsStart(VOID)
runProcess->processStatus = OS_PROCESS_RUNTASK_COUNT_ADD(runProcess->processStatus);
#endif
OS_SCHEDULER_SET(cpuid);//设置调度cpu id
OS_SCHEDULER_SET(cpuid);//设置可发生调度的cpuid
PRINTK("cpu %d entering scheduler\n", cpuid);
OsStartToRun(taskCB);//任务开始跑,注意OsStartToRun是一个汇编函数 见于 los_dispatch.s
......
......@@ -50,7 +50,7 @@
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
//cpuid转换 2 -> 0100
#define CPUID_TO_AFFI_MASK(cpuid) (0x1u << (cpuid))
/**
......@@ -479,10 +479,10 @@ typedef VOID *(*TSK_ENTRY_FUNC)(UINTPTR param1,
* You are not allowed to add any fields and adjust fields to the structure
*/
typedef struct {//用户态栈信息,(按递减满栈方式注解)
UINTPTR userArea; //用户区域
UINTPTR userSP; //用户态下栈底位置
UINTPTR userMapBase;//用户态下映射基地址,代表栈顶位置.
UINT32 userMapSize;//用户态下映射大小,代表栈大小
UINTPTR userArea; //用户空间的堆区开始位置
UINTPTR userSP; //用户空间当前栈指针位置
UINTPTR userMapBase;//用户空间的栈顶位置.
UINT32 userMapSize;//用户空间的栈大小,栈底 = userMapBase + userMapSize
} UserTaskParam;
/**
......
......@@ -45,7 +45,7 @@ LITE_USER_SEC_TEXT STATIC UINT32 sys_call3(UINT32 nbr, UINT32 parm1, UINT32 parm
register UINT32 reg1 __asm__("r1") = (UINT32)(parm2);//R1 = 参数2
register UINT32 reg0 __asm__("r0") = (UINT32)(parm1);//R0 = 参数1
//SVC指令会触发一个“特权调用”异常。这为非特权软件调用操作系统或其他只能在PL1级别访问的系统组件提供了一种机制。
//SVC指令会触发一个特权调用异常。这为非特权软件调用操作系统或其他只能在PL1级别访问的系统组件提供了一种机制。
__asm__ __volatile__
(
"svc %1" //管理模式(svc) [10011]:操作系统使用的保护模式
......@@ -53,7 +53,7 @@ LITE_USER_SEC_TEXT STATIC UINT32 sys_call3(UINT32 nbr, UINT32 parm1, UINT32 parm
: "i"(SYS_CALL_VALUE), "r"(reg7), "r"(reg0), "r"(reg1), "r"(reg2)
: "memory", "r14"
);
//相当于执行了 reset_vector_mp.S 中的 向量表0x08对应的 _osExceptSwiHdl
//相当于执行了 reset_vector_mp.S 中的 向量表0x08对应的 _osExceptSwiHdl
return reg0;//reg0的值将在汇编中改变.
}
......
git add -A
git commit -m '完善之前的一些注解
git commit -m '完善任务在用户态运行的注解
百万汉字注解 + 百篇博客分析 => 挖透鸿蒙内核源码
https://my.oschina.net/weharmony
'
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册