对sig_cb模块注解

    百万汉字注解 + 百篇博客分析 => 挖透鸿蒙内核源码
    https://my.oschina.net/weharmony
上级 650f4d6c
......@@ -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 地址,KPCRProcessor 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 @不相等,R00,一般是 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寄存器值
......
......@@ -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
......
......@@ -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.
......
......@@ -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;
......
......@@ -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 {//信号控制块(描述符)
......
......@@ -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 */
......
git add -A
git commit -m '文案整理,方便阅读
git commit -m '对sig_cb模块注解
百万汉字注解 + 百篇博客分析 => 挖透鸿蒙内核源码
https://my.oschina.net/weharmony
'
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册