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

CPU 硬件栈部分注释 解释 0xCCCCCCCC "烫烫烫烫" 的由来

鸿蒙内核源码分析系列 https://blog.csdn.net/kuangyufei https://my.oschina.net/u/3751245
鸿蒙内核源码注释中文版 【 CSDN仓 | Gitee仓 | Github仓 | Coding仓】四大仓库每日同步更新
给鸿蒙内核源码逐行加上中文注释 ,让高冷,楚楚动人的HarmonyOS不再神秘,从此镌刻在脑海中,陪你仗剑走天涯 :|P
上级 e96b7482
......@@ -72,28 +72,25 @@
* 鸿蒙源码分析系列篇: https://blog.csdn.net/kuangyufei
https://my.oschina.net/u/3751245
****************************************************************************
*
|-------------------|
| 0xCCCCCCCC |0x00000000 <---- stack top == OS_STACK_MAGIC_WORD
|-------------------|
| 0xCACACACA |0x00000004 == OS_STACK_INIT
|-------------------|
| 0xCACACACA |0x00000008
|-------------------|
| 0xCACACACA |//1.一个栈初始化时 栈顶为 0xCCCCCCCC 其余空间全为 0xCACACACA 这样很容易通过值得比较知道栈有没有溢出
|-------------------|//2.在虚拟地址的序列上 栈底是高于栈顶的
| 0xCACACACA |//3.sp在初始位置是指向栈底的
|-------------------|//4.还有多少0xCACACACA就代表使用的最高峰 peak used
| 0xCACACACA |//5.一旦栈顶不是0xCCCCCCCC,说明已经溢出了,检测栈的溢出就是通过 栈顶值是否等于0xCCCCCCCC
|-------------------|
| 0x89EF3245 |
|-------------------|
| 0x83 |0x0FFFFFF8 <--- sp
|-------------------|
| 0x75AB |0x0FFFFFFB
|-------------------|
| 0xC32F |
|-------------------|0x10000000 <---- stack bottom
+-------------------+0x00000000 <---- stack top == OS_STACK_MAGIC_WORD
| 0xCCCCCCCC |
+-------------------+0x00000004 == OS_STACK_INIT
| 0xCACACACA |
+-------------------+0x00000008
| 0xCACACACA |
+-------------------+ //1.一个栈初始化时 栈顶为 0xCCCCCCCC 其余空间全为 0xCACACACA 这样很容易通过值得比较知道栈有没有溢出
| 0xCACACACA | //2.在虚拟地址的序列上 栈底是高于栈顶的
+-------------------+ //3.sp在初始位置是指向栈底的
| 0xCACACACA | //4.还有多少0xCACACACA就代表使用的最高峰 peak used
+-------------------+ //5.一旦栈顶不是0xCCCCCCCC,说明已经溢出了,检测栈的溢出就是通过 栈顶值是否等于0xCCCCCCCC
| 0xCACACACA |
+-------------------+0x000000FF8 <--- sp
| 0xC32F9876 |
+-------------------+0x000000FFB
| 0x6543EB6 |
+-------------------+0x000001000 <---- stack bottom
*/
#ifdef LOSCFG_GDB
......@@ -128,4 +125,4 @@
#define REG_SP REG_R13 //堆栈指针 当不使用堆栈时,R13 也可以用做通用数据寄存器
#define REG_LR REG_R14 //连接寄存器。当执行子程序或者异常中断时,跳转指令会自动将当前地址存入LR寄存器中,当执行完子程 序或者中断后,根据LR中的值,恢复或者说是返回之前被打断的地址继续执行
#define REG_PC REG_R15 //指令寄存器
#endif
\ No newline at end of file
#endif
......@@ -105,26 +105,26 @@ STATIC UINT32 g_nextExcWaitCpu = INVALID_CPUID;
((ptr) <= g_maxAddr) && \
(IS_ALIGNED((ptr), sizeof(CHAR *))))
STATIC const StackInfo g_excStack[] = {
{ &__undef_stack, OS_EXC_UNDEF_STACK_SIZE, "udf_stack" },
{ &__abt_stack, OS_EXC_ABT_STACK_SIZE, "abt_stack" },
{ &__fiq_stack, OS_EXC_FIQ_STACK_SIZE, "fiq_stack" }, //快中断栈
{ &__svc_stack, OS_EXC_SVC_STACK_SIZE, "svc_stack" },
{ &__irq_stack, OS_EXC_IRQ_STACK_SIZE, "irq_stack" }, //中断请求栈
{ &__exc_stack, OS_EXC_STACK_SIZE, "exc_stack" } //运行
STATIC const StackInfo g_excStack[] = {// 6个执行栈
{ &__undef_stack, OS_EXC_UNDEF_STACK_SIZE, "udf_stack" }, //512 未定义的指令模式堆栈
{ &__abt_stack, OS_EXC_ABT_STACK_SIZE, "abt_stack" }, //512 中止模式堆栈,用于数据中止,可以将处理程序设置为在触发异常终止时运行
{ &__fiq_stack, OS_EXC_FIQ_STACK_SIZE, "fiq_stack" }, //64 FIQ中断模式堆栈.快速中断(FIQ)可能会在IRQ期间发生-它们就像优先级较高的IRQ.在FIQ中,FIQ和IRQ被禁用.
{ &__svc_stack, OS_EXC_SVC_STACK_SIZE, "svc_stack" }, //8K 主管模式堆栈.有些指令只能在SVC模式下运行
{ &__irq_stack, OS_EXC_IRQ_STACK_SIZE, "irq_stack" }, //64 中断(IRQ)模式堆栈.
{ &__exc_stack, OS_EXC_STACK_SIZE, "exc_stack" } //4K 用户和系统模式堆栈.大多数情况下,这是你用于执行代码的常规堆
};
//获取系统状态
UINT32 OsGetSystemStatus(VOID)
{
UINT32 flag;
UINT32 cpuID = g_currHandleExcCpuID;
UINT32 cpuID = g_currHandleExcCpuID;//全局变量 当前执行CPU ID
if (cpuID == INVALID_CPUID) {
flag = OS_SYSTEM_NORMAL;
} else if (cpuID == ArchCurrCpuid()) {
flag = OS_SYSTEM_EXC_CURR_CPU;
} else if (cpuID == ArchCurrCpuid()) {//真的是碰到了真在执行此处代码的CPU core
flag = OS_SYSTEM_EXC_CURR_CPU;//当前CPU
} else {
flag = OS_SYSTEM_EXC_OTHER_CPU;
flag = OS_SYSTEM_EXC_OTHER_CPU;//其他CPU
}
return flag;
......
......@@ -42,9 +42,9 @@ extern "C" {
#endif /* __cplusplus */
typedef struct {
VOID *stackTop;
UINT32 stackSize;
CHAR *stackName;
VOID *stackTop; //栈顶
UINT32 stackSize; //栈大小
CHAR *stackName; //栈名称
} StackInfo;
#define OS_INVALID_WATERLINE 0xFFFFFFFF
......
......@@ -65,7 +65,7 @@ LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrDestroy(LosMuxAttr *attr)
return LOS_OK;
}
//获取互斥锁的类型给outType
//获取互斥锁的类型属性,由outType接走,不送!
LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrGetType(const LosMuxAttr *attr, INT32 *outType)
{
INT32 type;
......@@ -83,7 +83,7 @@ LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrGetType(const LosMuxAttr *attr, INT32 *outTyp
return LOS_OK;
}
//设置互斥锁的类型为type
//设置互斥锁的类型属性
LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrSetType(LosMuxAttr *attr, INT32 type)
{
if ((attr == NULL) || (type < LOS_MUX_NORMAL) || (type > LOS_MUX_ERRORCHECK)) {
......@@ -93,7 +93,7 @@ LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrSetType(LosMuxAttr *attr, INT32 type)
attr->type = (UINT8)((attr->type & ~MUTEXATTR_TYPE_MASK) | (UINT32)type);
return LOS_OK;
}
//获取互斥锁属性的协议
//获取互斥锁的类型属性
LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrGetProtocol(const LosMuxAttr *attr, INT32 *protocol)
{
if ((attr != NULL) && (protocol != NULL)) {
......@@ -104,7 +104,7 @@ LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrGetProtocol(const LosMuxAttr *attr, INT32 *pr
return LOS_OK;
}
//获取互斥锁属性的协议
//设置互斥锁属性的协议
LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrSetProtocol(LosMuxAttr *attr, INT32 protocol)
{
if (attr == NULL) {
......@@ -134,7 +134,7 @@ LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrGetPrioceiling(const LosMuxAttr *attr, INT32
return LOS_OK;
}
//设置互斥锁属性优先级
//设置互斥锁属性的优先级的上限
LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrSetPrioceiling(LosMuxAttr *attr, INT32 prioceiling)
{
if ((attr == NULL) ||
......@@ -147,7 +147,7 @@ LITE_OS_SEC_TEXT UINT32 LOS_MuxAttrSetPrioceiling(LosMuxAttr *attr, INT32 prioce
return LOS_OK;
}
//设置互斥锁mutex的优先级,老优先级由oldPrioceiling带走
//设置互斥锁的优先级的上限,老优先级由oldPrioceiling带走
LITE_OS_SEC_TEXT UINT32 LOS_MuxSetPrioceiling(LosMux *mutex, INT32 prioceiling, INT32 *oldPrioceiling)
{
INT32 ret;
......@@ -176,7 +176,7 @@ LITE_OS_SEC_TEXT UINT32 LOS_MuxSetPrioceiling(LosMux *mutex, INT32 prioceiling,
return ret;
}
//获取互斥锁属性优先级
//获取互斥锁的优先级的上限
LITE_OS_SEC_TEXT UINT32 LOS_MuxGetPrioceiling(const LosMux *mutex, INT32 *prioceiling)
{
if ((mutex != NULL) && (prioceiling != NULL) && (mutex->magic == OS_MUX_MAGIC)) {
......@@ -236,7 +236,7 @@ LITE_OS_SEC_TEXT UINT32 LOS_MuxInit(LosMux *mutex, const LosMuxAttr *attr)
SCHEDULER_UNLOCK(intSave); //释放调度自旋锁
return LOS_OK;
}
//销毁互斥
//销毁互斥
LITE_OS_SEC_TEXT UINT32 LOS_MuxDestroy(LosMux *mutex)
{
UINT32 intSave;
......@@ -260,7 +260,7 @@ LITE_OS_SEC_TEXT UINT32 LOS_MuxDestroy(LosMux *mutex)
SCHEDULER_UNLOCK(intSave); //释放调度自旋锁
return LOS_OK;
}
//
//设置互斥锁位图
STATIC VOID OsMuxBitmapSet(const LosMux *mutex, const LosTaskCB *runTask, LosTaskCB *owner)
{ //当前任务优先级高于锁持有task时的处理
if ((owner->priority > runTask->priority) && (mutex->attr.protocol == LOS_MUX_PRIO_INHERIT)) {//协议用继承方式是怎么的呢?
......@@ -268,7 +268,7 @@ STATIC VOID OsMuxBitmapSet(const LosMux *mutex, const LosTaskCB *runTask, LosTas
OsTaskPriModify(owner, runTask->priority);//2.把高优先级的当前任务优先级设为持有锁任务的优先级.
}//注意任务优先级有32个, 是0最高,31最低!!!这里等于提高了持有锁任务的优先级,目的是让其在下次调度中提高选中的概率,从而快速的释放锁.您明白了吗? :|)
}
//恢复互斥锁位图
VOID OsMuxBitmapRestore(const LosMux *mutex, const LosTaskCB *taskCB, LosTaskCB *owner)
{
UINT16 bitMapPri;
......@@ -505,13 +505,13 @@ STATIC UINT32 OsMuxPostOp(LosTaskCB *taskCB, LosMux *mutex, BOOL *needSched)
{
LosTaskCB *resumedTask = NULL;
if (LOS_ListEmpty(&mutex->muxList)) {
LOS_ListDelete(&mutex->holdList);
if (LOS_ListEmpty(&mutex->muxList)) {//如果互斥锁列表为空
LOS_ListDelete(&mutex->holdList);//
mutex->owner = NULL;
return LOS_OK;
}
resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(mutex->muxList)));
resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(mutex->muxList)));//
if (mutex->attr.protocol == LOS_MUX_PRIO_INHERIT) {
if (resumedTask->priority > taskCB->priority) {
if (LOS_HighBitGet(taskCB->priBitMap) != resumedTask->priority) {
......@@ -527,7 +527,7 @@ STATIC UINT32 OsMuxPostOp(LosTaskCB *taskCB, LosMux *mutex, BOOL *needSched)
LOS_ListDelete(&mutex->holdList);
LOS_ListTailInsert(&resumedTask->lockList, &mutex->holdList);
OsTaskWake(resumedTask);
if (needSched != NULL) {// ????? 这个地方有点让人看不懂了,没有任何改变它的地方,完全由参数一路传下来的.
if (needSched != NULL) {
*needSched = TRUE;
}
......@@ -554,11 +554,11 @@ UINT32 OsMuxUnlockUnsafe(LosTaskCB *taskCB, LosMux *mutex, BOOL *needSched)
return LOS_EPERM;
}
//注意 --mutex->muxCount 先执行了-- 操作.
if ((--mutex->muxCount != 0) && (mutex->attr.type == LOS_MUX_RECURSIVE)) {//LOS_MUX_RECURSIVE 情况是可以不为0的
if ((--mutex->muxCount != 0) && (mutex->attr.type == LOS_MUX_RECURSIVE)) {//属性类型为LOS_MUX_RECURSIVE时,muxCount是可以不为0的
return LOS_OK;
}
if (mutex->attr.protocol == LOS_MUX_PRIO_PROTECT) {
if (mutex->attr.protocol == LOS_MUX_PRIO_PROTECT) {//属性协议为保护时
bitMapPri = LOS_HighBitGet(taskCB->priBitMap);//找priBitMap记录中最高的那个优先级
if (bitMapPri != LOS_INVALID_BIT_INDEX) {
LOS_BitmapClr(&taskCB->priBitMap, bitMapPri);//找priBitMap记录中最高的那个优先级
......@@ -596,7 +596,7 @@ LITE_OS_SEC_TEXT UINT32 LOS_MuxUnlock(LosMux *mutex)
ret = OsMuxUnlockUnsafe(runTask, mutex, &needSched);
SCHEDULER_UNLOCK(intSave);
if (needSched == TRUE) {//需要调度的情况
LOS_MpSchedule(OS_MP_CPU_ALL);//多CPU的情况
LOS_MpSchedule(OS_MP_CPU_ALL);//向所有CPU发送调度指令
LOS_Schedule();//发起调度
}
return ret;
......
......@@ -39,7 +39,7 @@
const StackInfo *g_stackInfo = NULL;
UINT32 g_stackNum;
//获取栈的水平线
//获取栈的吃水线
UINT32 OsStackWaterLineGet(const UINTPTR *stackBottom, const UINTPTR *stackTop, UINT32 *peakUsed)
{
UINT32 size;
......@@ -50,14 +50,14 @@ UINT32 OsStackWaterLineGet(const UINTPTR *stackBottom, const UINTPTR *stackTop,
tmp++;
}
size = (UINT32)((UINTPTR)stackBottom - (UINTPTR)tmp);//剩余多少非0xCACACACA的栈空间
*peakUsed = (size == 0) ? size : (size + sizeof(CHAR *));//得出高峰用值
*peakUsed = (size == 0) ? size : (size + sizeof(CHAR *));//得出高峰用值,还剩多少可用
return LOS_OK;
} else {
*peakUsed = OS_INVALID_WATERLINE;//栈溢出了
return LOS_NOK;
}
}
//执行栈检查
//执行栈检查,主要就是检查栈顶值有没有被改写
VOID OsExcStackCheck(VOID)
{
UINT32 index;
......@@ -70,14 +70,14 @@ VOID OsExcStackCheck(VOID)
for (index = 0; index < g_stackNum; index++) {
for (cpuid = 0; cpuid < LOSCFG_KERNEL_CORE_NUM; cpuid++) {
stackTop = (UINTPTR *)((UINTPTR)g_stackInfo[index].stackTop + cpuid * g_stackInfo[index].stackSize);
if (*stackTop != OS_STACK_MAGIC_WORD) {
if (*stackTop != OS_STACK_MAGIC_WORD) {// 只要栈顶内容不是 0xCCCCCCCCC 就是溢出了.
PRINT_ERR("cpu:%u %s overflow , magic word changed to 0x%x\n",
LOSCFG_KERNEL_CORE_NUM - 1 - cpuid, g_stackInfo[index].stackName, *stackTop);
}
}
}
}
//打印栈的信息 把每个CPU的栈信息打印出来
VOID OsExcStackInfo(VOID)
{
UINT32 index;
......@@ -92,12 +92,11 @@ VOID OsExcStackInfo(VOID)
PrintExcInfo("\n stack name cpu id stack addr total size used size\n"
" ---------- ------ --------- -------- --------\n");
for (index = 0; index < g_stackNum; index++) {
for (cpuid = 0; cpuid < LOSCFG_KERNEL_CORE_NUM; cpuid++) {
for (cpuid = 0; cpuid < LOSCFG_KERNEL_CORE_NUM; cpuid++) {//可以看出 各个CPU的栈是紧挨的的
stackTop = (UINTPTR *)((UINTPTR)g_stackInfo[index].stackTop + cpuid * g_stackInfo[index].stackSize);
stack = (UINTPTR *)((UINTPTR)stackTop + g_stackInfo[index].stackSize);
(VOID)OsStackWaterLineGet(stack, stackTop, &size);
(VOID)OsStackWaterLineGet(stack, stackTop, &size);//获取吃水线, 鸿蒙用WaterLine 这个词用的很妙
PrintExcInfo("%11s %-5d %-10p 0x%-8x 0x%-4x\n", g_stackInfo[index].stackName,
LOSCFG_KERNEL_CORE_NUM - 1 - cpuid, stackTop, g_stackInfo[index].stackSize, size);
......@@ -106,18 +105,40 @@ VOID OsExcStackInfo(VOID)
OsExcStackCheck();
}
/***************************************************************************************@note_pic
OsExcStackInfo 各个CPU栈布局图,其他栈也是一样,CPU各核硬件栈都是紧挨着
__undef_stack(SMP)
+-------------------+ <--- cpu1 top
| |
| CPU core1 |
| |
+--------------------<--- cpu2 top
| |
| cpu core 2 |
| |
+--------------------<--- cpu3 top
| |
| cpu core 3 |
| |
+--------------------<--- cpu4 top
| |
| cpu core 4 |
| |
+-------------------+
******************************************************************************************/
//注册栈信息
VOID OsExcStackInfoReg(const StackInfo *stackInfo, UINT32 stackNum)
{
g_stackInfo = stackInfo;
g_stackNum = stackNum;
}
//栈的初始化,设置固定的值. 0xcccccccc 和 0xcacacaca
//task栈的初始化,设置固定的值. 0xcccccccc 和 0xcacacaca
VOID OsStackInit(VOID *stacktop, UINT32 stacksize)
{
/* initialize the task stack, write magic num to stack top */
(VOID)memset_s(stacktop, stacksize, (INT32)OS_STACK_INIT, stacksize);
*((UINTPTR *)stacktop) = OS_STACK_MAGIC_WORD;
(VOID)memset_s(stacktop, stacksize, (INT32)OS_STACK_INIT, stacksize);//清一色填 0xCACACACA
*((UINTPTR *)stacktop) = OS_STACK_MAGIC_WORD;//0xCCCCCCCCC 中文就是"烫烫烫烫" 这几个字懂点计算机的人都不会陌生了.
}
#ifdef LOSCFG_SHELL_CMD_DEBUG
......
......@@ -49,7 +49,7 @@ enum {
LOS_MUX_PRIO_NONE = 0, //线程的优先级和调度不会受到互斥锁影响,先来后到,普通排队.
LOS_MUX_PRIO_INHERIT = 1, //当高优先级的等待低优先级的线程释放锁时,低优先级的线程以高优先级线程的优先级运行。
//当线程解锁互斥量时,线程的优先级自动被将到它原来的优先级
LOS_MUX_PRIO_PROTECT = 2 //
LOS_MUX_PRIO_PROTECT = 2 //详见:OsMuxPendOp中的注解,详细说明了LOS_MUX_PRIO_PROTECT的含义
};
enum {
......@@ -60,9 +60,9 @@ enum {
};
typedef struct {
UINT8 protocol;
UINT8 prioceiling;
UINT8 type;
UINT8 protocol; //协议
UINT8 prioceiling; //优先级上限
UINT8 type; //类型属性
UINT8 reserved;
} LosMuxAttr;
......
git add -A
git commit -m 'CPU core 的两个sort list(taskSortLink,swtmrSortLink)模块的注释
git commit -m 'CPU 硬件栈部分注释 解释 0xCCCCCCCC "烫烫烫烫" 的由来
鸿蒙内核源码分析系列 https://blog.csdn.net/kuangyufei https://my.oschina.net/u/3751245
鸿蒙内核源码注释中文版 【 CSDN仓 | Gitee仓 | Github仓 | Coding仓】四大仓库每日同步更新
给鸿蒙内核源码逐行加上中文注释 ,让 HarmonyOS 楚楚动人, 从此不再神秘.'
给鸿蒙内核源码逐行加上中文注释 ,让高冷,楚楚动人的HarmonyOS不再神秘,从此镌刻在脑海中,陪你仗剑走天涯 :|P'
git push origin
git push gitee_origin master
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册