diff --git a/arch/arm/arm/src/los_dispatch.S b/arch/arm/arm/src/los_dispatch.S index dfd05af7e14d038f85e9bb42dc2d4c9cbeca36b7..73c38d682646ae48a3df13f103cef1988f4f4a74 100644 --- a/arch/arm/arm/src/los_dispatch.S +++ b/arch/arm/arm/src/los_dispatch.S @@ -135,38 +135,47 @@ LDM/STR架构中{∧}为可选后缀,当指令为LDM且寄存器列表中包含R .macro PUSH_FPU_REGS reg1 /* 保存fpu寄存器 */ #if !defined(LOSCFG_ARCH_FPU_DISABLE) @FPU使能 VMRS \reg1, FPEXC - PUSH {\reg1} @对应TaskContext->regFPEXC + PUSH {\reg1} @对应 TaskContext->regFPEXC VMRS \reg1, FPSCR - PUSH {\reg1} @对应TaskContext->regFPSCR + PUSH {\reg1} @对应 TaskContext->regFPSCR #if defined(LOSCFG_ARCH_FPU_VFP_D32) - VPUSH {D16-D31} @对应TaskContext->D + VPUSH {D16-D31} @对应 TaskContext->D #endif - VPUSH {D0-D15} + VPUSH {D0-D15} @对应 TaskContext->D #endif .endm .macro POP_FPU_REGS reg1 /* 恢复fpu寄存器 */ #if !defined(LOSCFG_ARCH_FPU_DISABLE) - VPOP {D0-D15} + VPOP {D0-D15} @对应 TaskContext->D #if defined(LOSCFG_ARCH_FPU_VFP_D32) - VPOP {D16-D31} + VPOP {D16-D31} @对应 TaskContext->D #endif POP {\reg1} - VMSR FPSCR, \reg1 + VMSR FPSCR, \reg1 @对应 TaskContext->regFPSCR POP {\reg1} - VMSR FPEXC, \reg1 + VMSR FPEXC, \reg1 @对应 TaskContext->regFPEXC #endif .endm /* R0: new task */ -OsStartToRun: +OsStartToRun: @启动一个任务 MSR CPSR_c, #(CPSR_INT_DISABLE | CPSR_SVC_MODE) @禁止中断并切到管理模式 LDRH R1, [R0, #4] @将存储器地址为R0+4 的低16位数据读入寄存器R1,并将R1 的高16 位清零 ORR R1, #OS_TASK_STATUS_RUNNING @或指令 R1=R1|OS_TASK_STATUS_RUNNING STRH R1, [R0, #4] @将寄存器R1中的低16位写入以R0+4地址的存储器中 +/* +使用 TPIDRURO 保存当前线程的 KTHREAD 地址,KTHREAD 是每个线程在内 +核空间中的核心数据结构。C13 c0 3 + +使用 TPIDRURW 保存当前线程的 TEB 地址,TEB 是每个线程在用户空间中的核 +心数据结构。C13 c0 2 +使用 TPIDRPRW 保存当前 CPU 的 KPCR 地址,KPCR(Processor Control Region) +是每个 CPU 的核心数据结构地址。C13 c0 4 +*/ /* R0 is new task, save it on tpidrprw */ MCR p15, 0, R0, c13, c0, 4 @ C13=R0 ISB @指令同步屏障,清除流水线并且确保在新指令执行时,之前的指令都已经执行完毕。 @@ -319,12 +328,12 @@ OsIrqFromKernel: @从内核发起中断 BL OsTaskProcSignal @跳转至C代码 /* check if needs to schedule */@检查是否需要调度 - CMP R0, #0 @是否需要调度,R0为参数保存值 - BLNE OsSchedPreempt @不相等,即R0非0,一般是 1 + CMP R0, #0 @OsTaskProcSignal的返回值 和 0 进行比较 + BLNE OsSchedPreempt @返回INT_PEND_RESCH,则执行 OsSchedPreempt - MOV R0,SP @参数 - MOV R1,R7 @参数 - BL OsSaveSignalContextIrq @跳转至C代码 + MOV R0,SP @TaskIrqContext开始位置 + MOV R1,R7 @第二个参数,R7 + BL OsSaveSignalContextIrq @保存信号上下文 /* restore fpu regs */ POP_FPU_REGS R0 @恢复fpu寄存器值 diff --git a/arch/arm/arm/src/los_exc.c b/arch/arm/arm/src/los_exc.c index 2580f3b20993a0c69d64021a8b07849c0ab9a324..1d34e21c926a72a21b12cea271a4df7f49d2abd1 100644 --- a/arch/arm/arm/src/los_exc.c +++ b/arch/arm/arm/src/los_exc.c @@ -838,7 +838,7 @@ VOID OsUndefIncExcHandleEntry(ExcContext *excBufAddr) } while (1) {} } -//预取异常处理函数,由汇编调用 见于 los_hw_exc.s +//预取指令异常处理函数,由汇编调用 见于 los_hw_exc.s #if __LINUX_ARM_ARCH__ >= 7 VOID OsPrefetchAbortExcHandleEntry(ExcContext *excBufAddr) { @@ -1055,7 +1055,7 @@ LITE_OS_SEC_TEXT_INIT VOID OsExcHandleEntry(UINT32 excType, ExcContext *excBufAd /* Task scheduling is not allowed during exception handling *///异常处理期间不允许任务调度 OsPercpuGet()->taskLockCnt++;// - g_curNestCount[ArchCurrCpuid()]++; + g_curNestCount[ArchCurrCpuid()]++;//记录当前CPU异常数量 OsExcPriorDisposal(excBufAddr); @@ -1078,11 +1078,11 @@ LITE_OS_SEC_TEXT_INIT VOID OsExcHandleEntry(UINT32 excType, ExcContext *excBufAd #endif #ifdef LOSCFG_SHELL_EXCINFO - log_read_write_fn func = GetExcInfoRW(); + log_read_write_fn func = GetExcInfoRW();//获取异常信息读写函数,用于打印异常信息栈 #endif - if (g_excHook != NULL) { - if (g_curNestCount[ArchCurrCpuid()] == 1) { + if (g_excHook != NULL) {//全局异常钩子函数 + if (g_curNestCount[ArchCurrCpuid()] == 1) {//说明只有一个异常 #ifdef LOSCFG_SHELL_EXCINFO if (func != NULL) { SetExcInfoIndex(0); @@ -1092,8 +1092,8 @@ LITE_OS_SEC_TEXT_INIT VOID OsExcHandleEntry(UINT32 excType, ExcContext *excBufAd } #endif g_excHook(excType, excBufAddr, far, fsr); - } else { - OsCallStackInfo(); + } else {//说明出现了异常嵌套的情况 + OsCallStackInfo();//打印栈内容 } #ifdef LOSCFG_SHELL_EXCINFO diff --git a/arch/arm/arm/src/los_hw_exc.S b/arch/arm/arm/src/los_hw_exc.S index 52ea9b7e27dffbb5a47053cd10cd04c92f5f0eec..230e8a8d439fa1ca20b7218b1adda13673a9aadf 100644 --- a/arch/arm/arm/src/los_hw_exc.S +++ b/arch/arm/arm/src/los_hw_exc.S @@ -33,23 +33,23 @@ #include "arch_config.h" .extern g_losTask - .extern g_intCount - .extern g_curNestCount + .extern g_intCount @中断数量数组 + .extern g_curNestCount @异常嵌套数量数组 .extern OsExcHandleEntry @异常处理入口 .extern __svc_stack_top @管理栈顶位置 操作系统使用的保护模式 - .extern __exc_stack_top @任务栈顶位置 + .extern __exc_stack_top @异常栈顶位置 .extern __stack_chk_guard .extern OsRandomStackGuard #ifdef LOSCFG_GDB - .extern OsUndefIncExcHandleEntry + .extern OsUndefIncExcHandleEntry @未定义指令异常处理函数 #if __LINUX_ARM_ARCH__ >= 7 - .extern OsPrefetchAbortExcHandleEntry - .extern OsDataAbortExcHandleEntry + .extern OsPrefetchAbortExcHandleEntry @预取指令终止异常处理函数 + .extern OsDataAbortExcHandleEntry @数据终止异常处理函数 #endif #endif - .extern OsArmSharedPageFault - .extern OsArmA32SyscallHandle - .extern LOS_Exit + .extern OsArmSharedPageFault @共享缺页中断处理函数 + .extern OsArmA32SyscallHandle @系统调用处理函数 + .extern LOS_Exit @进程退出 .global _osExceptFiqHdl .global _osExceptAddrAbortHdl @@ -236,7 +236,7 @@ OsKernelSVCHandler:@主要目的是保存ExcContext中除(R0~R12)的其他寄存 _osExceptPrefetchAbortHdl: @预取异常处理 #ifdef LOSCFG_GDB #if __LINUX_ARM_ARCH__ >= 7 - GDB_HANDLE OsPrefetchAbortExcHandleEntry + GDB_HANDLE OsPrefetchAbortExcHandleEntry @取指令终止异常处理入口 #endif #else SUB LR, LR, #4 @ LR offset to return from this exception: -4. @@ -259,7 +259,7 @@ _osKernelExceptPrefetchAbortHdl: _osExceptDataAbortHdl: @数据异常处理,缺页就属于数据异常 #ifdef LOSCFG_GDB #if __LINUX_ARM_ARCH__ >= 7 - GDB_HANDLE OsDataAbortExcHandleEntry + GDB_HANDLE OsDataAbortExcHandleEntry @取数据终止异常处理入口 #endif #else SUB LR, LR, #8 @ LR offset to return from this exception: -8. diff --git a/kernel/base/core/los_task.c b/kernel/base/core/los_task.c index bb67e10ee4d03caa58405b1ceb6908a2d688391f..d15970435775cc95e4e8a658f02afa9d2eaf483b 100644 --- a/kernel/base/core/los_task.c +++ b/kernel/base/core/los_task.c @@ -1696,7 +1696,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 OsTaskProcSignal(VOID) * so it keeps recieving signals while follow code excuting. */ runTask = OsCurrTaskGet();//获取当前任务 - if (runTask->signal == SIGNAL_NONE) { + if (runTask->signal == SIGNAL_NONE) {//无任务信号 goto EXIT; } @@ -1712,25 +1712,25 @@ LITE_OS_SEC_TEXT_MINOR UINT32 OsTaskProcSignal(VOID) PRINT_ERR("Task proc signal delete task(%u) failed err:0x%x\n", runTask->taskID, ret); } } else if (runTask->signal & SIGNAL_SUSPEND) {//意思是其他cpu发起了要挂起你的信号 - runTask->signal &= ~SIGNAL_SUSPEND;// + runTask->signal &= ~SIGNAL_SUSPEND;//任务贴上被其他CPU挂起的标签 /* suspend killed task may fail, ignore the result */ (VOID)LOS_TaskSuspend(runTask->taskID); #if (LOSCFG_KERNEL_SMP == YES) } else if (runTask->signal & SIGNAL_AFFI) {//意思是下次调度其他cpu要媾和你 - runTask->signal &= ~SIGNAL_AFFI; + runTask->signal &= ~SIGNAL_AFFI;//任务贴上被其他CPU媾和的标签 /* pri-queue has updated, notify the target cpu */ - LOS_MpSchedule((UINT32)runTask->cpuAffiMask);//任务队列已更新,通知目标cpu + LOS_MpSchedule((UINT32)runTask->cpuAffiMask);//发生调度,此任务将移交给媾和CPU运行. #endif } EXIT: /* check if needs to schedule */ - percpu = OsPercpuGet(); - if (OsPreemptable() && (percpu->schedFlag == INT_PEND_RESCH)) { - percpu->schedFlag = INT_NO_RESCH; - return INT_PEND_RESCH; + percpu = OsPercpuGet();//获取当前CPU信息 + if (OsPreemptable() && (percpu->schedFlag == INT_PEND_RESCH)) {//注意这是CPU的调度标识,而不是任务的. + percpu->schedFlag = INT_NO_RESCH;//贴上不需要调度的标签 + return INT_PEND_RESCH;//返回需要调度,返回值后的指令是: CMP R0, #0 ,BLNE OsSchedPreempt ,如此将发生一轮调度. } return INT_NO_RESCH; diff --git a/kernel/base/include/los_signal.h b/kernel/base/include/los_signal.h index 8cf104c910d73ec33f13bcbd7222d6f1299e2682..b1854aee5e8c690a08d00a6ed637ddfd8942353e 100644 --- a/kernel/base/include/los_signal.h +++ b/kernel/base/include/los_signal.h @@ -209,7 +209,7 @@ typedef struct {//任务中断上下文 typedef struct {//信号切换上下文 TASK_IRQ_CONTEXT unsigned int R7; //存放系统调用的ID - unsigned int count; //信号上下文的数量 + unsigned int count; //记录是否保存了任务上下文 } sig_switch_context; typedef struct {//信号控制块(描述符) diff --git a/kernel/base/ipc/los_signal.c b/kernel/base/ipc/los_signal.c index 247a3db05a33acb61212c7955fab570631e705a1..647cbc57f891abf0c22d18220a8a711850ce5448 100644 --- a/kernel/base/ipc/los_signal.c +++ b/kernel/base/ipc/los_signal.c @@ -497,7 +497,7 @@ int OsSigTimedWait(sigset_t *set, siginfo_t *info, unsigned int timeout) SCHEDULER_UNLOCK(intSave); return ret; } -//让当前任务暂停的信号 +//通过信号挂起当前任务 int OsPause(void) { LosTaskCB *spcb = NULL; @@ -581,7 +581,7 @@ void OsSaveSignalContext(unsigned int *sp) unsigned long cpsr; OS_RETURN_IF_VOID(sp == NULL); - cpsr = OS_SYSCALL_GET_CPSR(sp); + cpsr = OS_SYSCALL_GET_CPSR(sp);//获取系统调用时的 CPSR值 OS_RETURN_IF_VOID(((cpsr & CPSR_MASK_MODE) != CPSR_USER_MODE));//必须在用户模式下保存 SCHEDULER_LOCK(intSave); @@ -590,7 +590,7 @@ void OsSaveSignalContext(unsigned int *sp) sigcb = &task->sig;//获取任务的信号控制块 if ((sigcb->context.count == 0) && ((sigcb->sigFlag != 0) || (process->sigShare != 0))) {//未保存上下文且关注了信号 - sigHandler = OsGetSigHandler(); + sigHandler = OsGetSigHandler();//获取信号处理函数 if (sigHandler == 0) {//信号没有注册 sigcb->sigFlag = 0; process->sigShare = 0; @@ -603,18 +603,18 @@ void OsSaveSignalContext(unsigned int *sp) unsigned int signo = (unsigned int)FindFirstSetedBit(sigcb->sigFlag) + 1; OsProcessExitCodeSignalSet(process, signo); sigcb->context.CPSR = cpsr; //保存当前各寄存器的信息 - sigcb->context.PC = sp[REG_PC]; + sigcb->context.PC = sp[REG_PC]; //获取被打断现场寄存器的值 sigcb->context.USP = sp[REG_SP]; sigcb->context.ULR = sp[REG_LR]; sigcb->context.R0 = sp[REG_R0]; sigcb->context.R1 = sp[REG_R1]; sigcb->context.R2 = sp[REG_R2]; - sigcb->context.R3 = sp[REG_R3]; - sigcb->context.R7 = sp[REG_R7]; - sigcb->context.R12 = sp[REG_R12]; - sp[REG_PC] = sigHandler;//下一个要执行的函数,信号注册函数 - sp[REG_R0] = signo; //信号注册函数参数 - sp[REG_R1] = (unsigned int)(UINTPTR)(sigcb->sigunbinfo.si_value.sival_ptr); //@note_why 这里没看明白是什么意思? + sigcb->context.R3 = sp[REG_R3]; + sigcb->context.R7 = sp[REG_R7];//为何参数不用传R7,是因为系统调用发生时 R7始终保存的是系统调用号. + sigcb->context.R12 = sp[REG_R12];//详见 https://my.oschina.net/weharmony/blog/4967613 + sp[REG_PC] = sigHandler;//指定信号执行函数,注意此处改变保存任务上下文中PC寄存器的值,恢复上下文时将执行这个函数. + sp[REG_R0] = signo; //参数1,信号ID + sp[REG_R1] = (unsigned int)(UINTPTR)(sigcb->sigunbinfo.si_value.sival_ptr); //参数2 /* sig No bits 00000100 present sig No 3, but 1<< 3 = 00001000, so signo needs minus 1 */ sigcb->sigFlag ^= 1ULL << (signo - 1); sigcb->context.count++; //代表已保存 @@ -623,7 +623,7 @@ void OsSaveSignalContext(unsigned int *sp) SCHEDULER_UNLOCK(intSave); } //发生硬中断时,需保存用户态的用户栈现场,多了一个参数 R7寄存器 -//汇编调用 见于 los_dispatch.S | 254行: BL OsSaveSignalContextIrq +//汇编调用 见于 los_dispatch.S | BL OsSaveSignalContextIrq void OsSaveSignalContextIrq(unsigned int *sp, unsigned int r7) { UINTPTR sigHandler; @@ -641,12 +641,12 @@ void OsSaveSignalContextIrq(unsigned int *sp, unsigned int r7) SCHEDULER_LOCK(intSave); task = OsCurrTaskGet(); //获取当前任务 process = OsCurrProcessGet(); - sigcb = &task->sig; + sigcb = &task->sig;//获取任务的信号控制块 if ((sigcb->context.count == 0) && ((sigcb->sigFlag != 0) || (process->sigShare != 0))) { - sigHandler = OsGetSigHandler(); - if (sigHandler == 0) { - sigcb->sigFlag = 0; - process->sigShare = 0; + sigHandler = OsGetSigHandler();//获取进程的信号处理函数 + if (sigHandler == 0) {//没有设置处理函数 + sigcb->sigFlag = 0;//进程没有设置信号处理函数,所以任务的信号无意义,标签回0 + process->sigShare = 0;//进程的共享位也无意义,回0 SCHEDULER_UNLOCK(intSave); PRINT_ERR("The current process pid =%d starts fail!\n", task->processID); return; @@ -654,9 +654,11 @@ void OsSaveSignalContextIrq(unsigned int *sp, unsigned int r7) sigcb->sigFlag |= process->sigShare; unsigned int signo = (unsigned int)FindFirstSetedBit(sigcb->sigFlag) + 1; OsProcessExitCodeSignalSet(process, signo); - (VOID)memcpy_s(&sigcb->context.R0, sizeof(TaskIrqDataSize), &context->R0, sizeof(TaskIrqDataSize));//note_why 为何此处和OsSaveSignalContext的处理不一致? - sigcb->context.R7 = r7; - context->PC = sigHandler;//入口函数 + (VOID)memcpy_s(&sigcb->context.R0, sizeof(TaskIrqDataSize), &context->R0, sizeof(TaskIrqDataSize));//拷贝中断上下文到任务的信号上下文 + //这里其实类似于 OsSaveSignalContext 中的 sigcb->context.USP = sp[REG_SP] ... + sigcb->context.R7 = r7;//因为是硬件触发,所以此处不同于 OsSaveSignalContext(unsigned int *sp),需要通过底层将 R7 带过来. MOV R1,R7, BL OsSaveSignalContextIrq + //同样的改变了栈中PC,R0,R1的值,意味着恢复现场后将执行 sigHandler(R0,R1) + context->PC = sigHandler;//信号入口函数 context->R0 = signo; //参数1 context->R1 = (UINT32)(UINTPTR)sigcb->sigunbinfo.si_value.sival_ptr;//参数2 /* sig No bits 00000100 present sig No 3, but 1<< 3 = 00001000, so signo needs minus 1 */ diff --git a/zzz/git/push.sh b/zzz/git/push.sh index d556b499e2a9eb8b723319540b13f92124407845..6058e872a8b3cce129c2b63f2dad6a09cc8c7294 100644 --- a/zzz/git/push.sh +++ b/zzz/git/push.sh @@ -1,5 +1,5 @@ git add -A -git commit -m '文案整理,方便阅读 +git commit -m '对sig_cb模块注解 百万汉字注解 + 百篇博客分析 => 挖透鸿蒙内核源码 https://my.oschina.net/weharmony '