Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
鸿蒙内核源码分析
注释鸿蒙内核源码
提交
218bf115
注释鸿蒙内核源码
项目概览
鸿蒙内核源码分析
/
注释鸿蒙内核源码
通知
270
Star
29
Fork
11
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
106
Wiki
分析
仓库
DevOps
项目成员
Pages
注释鸿蒙内核源码
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
106
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
218bf115
编写于
3月 31, 2021
作者:
鸿蒙内核源码分析
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
对sig_cb模块注解
百万汉字注解 + 百篇博客分析 => 挖透鸿蒙内核源码
https://my.oschina.net/weharmony
上级
650f4d6c
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
72 addition
and
61 deletion
+72
-61
arch/arm/arm/src/los_dispatch.S
arch/arm/arm/src/los_dispatch.S
+23
-14
arch/arm/arm/src/los_exc.c
arch/arm/arm/src/los_exc.c
+7
-7
arch/arm/arm/src/los_hw_exc.S
arch/arm/arm/src/los_hw_exc.S
+11
-11
kernel/base/core/los_task.c
kernel/base/core/los_task.c
+8
-8
kernel/base/include/los_signal.h
kernel/base/include/los_signal.h
+1
-1
kernel/base/ipc/los_signal.c
kernel/base/ipc/los_signal.c
+21
-19
zzz/git/push.sh
zzz/git/push.sh
+1
-1
未找到文件。
arch/arm/arm/src/los_dispatch.S
浏览文件 @
218bf115
...
...
@@ -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
寄存器值
...
...
arch/arm/arm/src/los_exc.c
浏览文件 @
218bf115
...
...
@@ -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
...
...
arch/arm/arm/src/los_hw_exc.S
浏览文件 @
218bf115
...
...
@@ -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
.
...
...
kernel/base/core/los_task.c
浏览文件 @
218bf115
...
...
@@ -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
;
...
...
kernel/base/include/los_signal.h
浏览文件 @
218bf115
...
...
@@ -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
{
//信号控制块(描述符)
...
...
kernel/base/ipc/los_signal.c
浏览文件 @
218bf115
...
...
@@ -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 */
...
...
zzz/git/push.sh
浏览文件 @
218bf115
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.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录