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

开始对信号量这块代码进行注释,信号量的出现为了解决task的同步问题

鸿蒙内核源码分析系列 【 CSDN | OSCHINA | WIKI 】
鸿蒙内核源码注释中文版 【 CSDN仓 | Gitee仓 | Github仓 | Coding仓 】四大仓库每日同步更新代码和wiki
给鸿蒙内核源码逐行加上中文注解,详细阐述设计细节, 助你快速精读 HarmonyOS 内核源码, 掌握整个鸿蒙内核运行机制.
上级 c7eee5a9
[鸿蒙内核源码注释中文版 【 Gitee仓](https://gitee.com/weharmony/kernel_liteos_a_note) | [CSDN仓](https://codechina.csdn.net/kuangyufei/kernel_liteos_a_note) | [Github仓](https://github.com/kuangyufei/kernel_liteos_a_note) | [Coding仓 】](https://weharmony.coding.net/public/harmony/kernel_liteos_a_note/git/files) 给 HarmonyOS 源码逐行加上中文注解,详细阐述设计细节, 助你快速精读 HarmonyOS 内核源码, 掌握整个鸿蒙内核运行机制,四大码仓和wiki每日同步更新. [鸿蒙内核源码注释中文版 【 Gitee仓 ](https://gitee.com/weharmony/kernel_liteos_a_note) | [ CSDN仓 ](https://codechina.csdn.net/kuangyufei/kernel_liteos_a_note) | [ Github仓 ](https://github.com/kuangyufei/kernel_liteos_a_note) | [ Coding仓 】](https://weharmony.coding.net/public/harmony/kernel_liteos_a_note/git/files) 给 HarmonyOS 源码逐行加上中文注解,详细阐述设计细节, 助你快速精读 HarmonyOS 内核源码, 掌握整个鸿蒙内核运行机制,四大码仓和wiki每日同步更新.
[鸿蒙源码分析系列篇 【 CSDN](https://blog.csdn.net/kuangyufei/article/details/108727970) [| OSCHINA](https://my.oschina.net/u/3751245/blog/4626852) [| WIKI 】](https://gitee.com/weharmony/kernel_liteos_a_note/wikis/pages) 从 HarmonyOS 架构层视角整理成文, 并首创用生活场景讲故事的方式试图去解构内核,一窥究竟。 [鸿蒙源码分析系列篇 【 CSDN ](https://blog.csdn.net/kuangyufei/article/details/108727970) [| OSCHINA ](https://my.oschina.net/u/3751245/blog/4626852) [| WIKI 】](https://gitee.com/weharmony/kernel_liteos_a_note/wikis/pages) 从 HarmonyOS 架构层视角整理成文, 并首创用生活场景讲故事的方式试图去解构内核,一窥究竟。
--- ---
# **[kernel\_liteos\_a_note](https://gitee.com/weharmony/kernel_liteos_a_note): 鸿蒙内核源码注释中文版** # **[kernel\_liteos\_a_note](https://gitee.com/weharmony/kernel_liteos_a_note): 鸿蒙内核源码注释中文版**
[![star](https://gitee.com/weharmony/kernel_liteos_a_note/badge/star.svg?theme=dark)](https://gitee.com/weharmony/kernel_liteos_a_note/stargazers)[![Fork me on Gitee](https://gitee.com/oschina/git-osc/widgets/widget_3.svg)](https://gitee.com/oschina/git-osc)[![fork](https://gitee.com/weharmony/kernel_liteos_a_note/badge/fork.svg?theme=dark)](https://gitee.com/weharmony/kernel_liteos_a_note/members)
每个码农,职业生涯,都应精读一遍内核源码. 鸿蒙内核源码就是很好的精读项目.一旦熟悉内核代码级实现,将迅速拔高对计算机整体理解,从此高屋建瓴看问题. 每个码农,职业生涯,都应精读一遍内核源码. 鸿蒙内核源码就是很好的精读项目.一旦熟悉内核代码级实现,将迅速拔高对计算机整体理解,从此高屋建瓴看问题.
## **做了些什么呢** ## **做了些什么呢**
**[kernel\_liteos\_a_note](https://gitee.com/weharmony/kernel_liteos_a_note)** 是在鸿蒙官方开源项目 **[OpenHarmony/kernel\_liteos\_a](https://gitee.com/openharmony/kernel_liteos_a)** 基础上给源码加上中文注解的版本,目前几大核心模块加注已基本完成,正持续加注完善中... **[kernel\_liteos\_a_note](https://gitee.com/weharmony/kernel_liteos_a_note)** 是在鸿蒙官方开源项目 **[OpenHarmony/kernel\_liteos\_a](https://gitee.com/openharmony/kernel_liteos_a)** 基础上给源码加上中文注解的版本,目前几大核心模块加注已基本完成,正持续加注完善中...
...@@ -52,11 +55,7 @@ ...@@ -52,11 +55,7 @@
- ### **新增的zzz目录是干什么的?** - ### **新增的zzz目录是干什么的?**
中文加注版比官方版无新增文件,只多了一个zzz的目录,里面放了一些笔者使用的文件,它与内核代码无关,大家可以忽略它,取名zzz是为了排在最后,减少对原有代码目录级的侵入,zzz的想法源于微信中名称为AAA的那批牛人,你的微信里应该也有他们熟悉的身影吧 :|P 中文加注版比官方版无新增文件,只多了一个zzz的目录,里面放了一些笔者使用的文件,它与内核代码无关,大家可以忽略它,取名zzz是为了排在最后,减少对原有代码目录级的侵入,zzz的想法源于微信中名称为AAA的那批牛人,你的微信里应该也有他们熟悉的身影吧 :|P
- ### **笔者联系方式**
邮箱: [kuangyufei@126.com](mailto:kuangyufei@126.com) 私信请不要问没有基础能不能学? 兴趣是最好的老师,有兴趣一定能成,什么是兴趣, 不是一两天的头脑发热而是每天吃饭睡觉都在想着这个事的. 更不要问如何看待 鸿蒙 PK Android ? 用了多少别人的源码之类的问题. 因为时间太宝贵, 大量的工作要完成. 不建议没经过深度思考就人云亦云,亦步亦趋. 如果非要纠结就想想QQ和微信的关系? 为何有了QQ还得有个微信,而且得由不同的BG来开发. 去翻翻微信刚出来那会有多少看不懂而质疑的声音. 笔者坚信鸿蒙未来一定可以很成功,誓做鸿蒙坚定的追随者和传播者.
- ### **既然选择了远方,就不要怕天高路远,行动起来!** - ### **既然选择了远方,就不要怕天高路远,行动起来!**
......
...@@ -1363,7 +1363,7 @@ UINT32 OsTaskWait(LOS_DL_LIST *list, UINT32 timeout, BOOL needSched) ...@@ -1363,7 +1363,7 @@ UINT32 OsTaskWait(LOS_DL_LIST *list, UINT32 timeout, BOOL needSched)
runTask->taskStatus |= OS_TASK_STATUS_PEND;//给任务贴上阻塞任务标签 runTask->taskStatus |= OS_TASK_STATUS_PEND;//给任务贴上阻塞任务标签
LOS_ListTailInsert(list, pendObj);//将阻塞任务挂到list上,,这步很关键,很重要! LOS_ListTailInsert(list, pendObj);//将阻塞任务挂到list上,,这步很关键,很重要!
if (timeout != LOS_WAIT_FOREVER) {//非永远等待的时候 if (timeout != LOS_WAIT_FOREVER) {//非永远等待的时候
runTask->taskStatus |= OS_TASK_STATUS_PEND_TIME;//阻塞任务再贴上一段时间内阻塞 runTask->taskStatus |= OS_TASK_STATUS_PEND_TIME;//阻塞任务再贴上在一段时间内阻塞的标签
OsAdd2TimerList(runTask, timeout);//把任务加到定时器链表中 OsAdd2TimerList(runTask, timeout);//把任务加到定时器链表中
} }
......
...@@ -45,11 +45,11 @@ extern "C" { ...@@ -45,11 +45,11 @@ extern "C" {
* Semaphore control structure. * Semaphore control structure.
*/ */
typedef struct { typedef struct {
UINT8 semStat; /**< Semaphore state */ UINT8 semStat; /**< Semaphore state *///信号量的状态
UINT16 semCount; /**< Number of available semaphores */ UINT16 semCount; /**< Number of available semaphores *///有效信号量的数量
UINT16 maxSemCount; /**< Max number of available semaphores */ UINT16 maxSemCount; /**< Max number of available semaphores *///有效信号量的最大数量
UINT32 semID; /**< Semaphore control structure ID */ UINT32 semID; /**< Semaphore control structure ID *///信号ID
LOS_DL_LIST semList; /**< Queue of tasks that are waiting on a semaphore */ LOS_DL_LIST semList; /**< Queue of tasks that are waiting on a semaphore *///等待信号量的任务队列,作为一个节点挂上去
} LosSemCB; } LosSemCB;
/** /**
......
...@@ -61,7 +61,7 @@ extern "C" { ...@@ -61,7 +61,7 @@ extern "C" {
#define SIGNAL_AFFI (1U << 2) #define SIGNAL_AFFI (1U << 2)
/* scheduler lock */ /* scheduler lock */
extern SPIN_LOCK_S g_taskSpin; extern SPIN_LOCK_S g_taskSpin;//任务自旋锁
#define SCHEDULER_LOCK(state) LOS_SpinLockSave(&g_taskSpin, &(state)) #define SCHEDULER_LOCK(state) LOS_SpinLockSave(&g_taskSpin, &(state))
#define SCHEDULER_UNLOCK(state) LOS_SpinUnlockRestore(&g_taskSpin, state) #define SCHEDULER_UNLOCK(state) LOS_SpinUnlockRestore(&g_taskSpin, state)
......
...@@ -50,8 +50,8 @@ extern "C" { ...@@ -50,8 +50,8 @@ extern "C" {
#error "sem maxnum cannot be zero" #error "sem maxnum cannot be zero"
#endif /* LOSCFG_BASE_IPC_SEM_LIMIT <= 0 */ #endif /* LOSCFG_BASE_IPC_SEM_LIMIT <= 0 */
LITE_OS_SEC_DATA_INIT STATIC LOS_DL_LIST g_unusedSemList; LITE_OS_SEC_DATA_INIT STATIC LOS_DL_LIST g_unusedSemList;//可用的信号量列表,干嘛不用freeList? 可以看出这里是另一个人写的代码
LITE_OS_SEC_BSS LosSemCB *g_allSem = NULL; LITE_OS_SEC_BSS LosSemCB *g_allSem = NULL;//信号池,一次分配 LOSCFG_BASE_IPC_SEM_LIMIT 个信号量
/* /*
* Description : Initialize the semaphore doubly linked list * Description : Initialize the semaphore doubly linked list
...@@ -62,18 +62,18 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsSemInit(VOID)//信号量初始化 ...@@ -62,18 +62,18 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsSemInit(VOID)//信号量初始化
LosSemCB *semNode = NULL; LosSemCB *semNode = NULL;
UINT32 index; UINT32 index;
LOS_ListInit(&g_unusedSemList); LOS_ListInit(&g_unusedSemList);//初始
/* system resident memory, don't free */ /* system resident memory, don't free */
g_allSem = (LosSemCB *)LOS_MemAlloc(m_aucSysMem0, (LOSCFG_BASE_IPC_SEM_LIMIT * sizeof(LosSemCB))); g_allSem = (LosSemCB *)LOS_MemAlloc(m_aucSysMem0, (LOSCFG_BASE_IPC_SEM_LIMIT * sizeof(LosSemCB)));//分配信号池
if (g_allSem == NULL) { if (g_allSem == NULL) {
return LOS_ERRNO_SEM_NO_MEMORY; return LOS_ERRNO_SEM_NO_MEMORY;
} }
for (index = 0; index < LOSCFG_BASE_IPC_SEM_LIMIT; index++) { for (index = 0; index < LOSCFG_BASE_IPC_SEM_LIMIT; index++) {
semNode = ((LosSemCB *)g_allSem) + index; semNode = ((LosSemCB *)g_allSem) + index;//拿信号控制块, 可以直接g_allSem[index]来嘛
semNode->semID = SET_SEM_ID(0, index); semNode->semID = SET_SEM_ID(0, index);//保存ID
semNode->semStat = OS_SEM_UNUSED; semNode->semStat = OS_SEM_UNUSED;//标记未使用
LOS_ListTailInsert(&g_unusedSemList, &semNode->semList); LOS_ListTailInsert(&g_unusedSemList, &semNode->semList);//通过semList把 信号块挂到空闲链表上
} }
if (OsSemDbgInitHook() != LOS_OK) { if (OsSemDbgInitHook() != LOS_OK) {
...@@ -101,26 +101,26 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsSemCreate(UINT16 count, UINT16 maxCount, UINT32 * ...@@ -101,26 +101,26 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsSemCreate(UINT16 count, UINT16 maxCount, UINT32 *
return LOS_ERRNO_SEM_PTR_NULL; return LOS_ERRNO_SEM_PTR_NULL;
} }
if (count > maxCount) { if (count > maxCount) {//信号量不能大于最大值,两参数都是外面给的
OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_OVERFLOW); OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_OVERFLOW);
} }
SCHEDULER_LOCK(intSave); SCHEDULER_LOCK(intSave);//进入临界区了,拿自旋锁
if (LOS_ListEmpty(&g_unusedSemList)) { if (LOS_ListEmpty(&g_unusedSemList)) {//没有可分配的空闲信号提供
SCHEDULER_UNLOCK(intSave); SCHEDULER_UNLOCK(intSave);
OsSemInfoGetFullDataHook(); OsSemInfoGetFullDataHook();
OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_ALL_BUSY); OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_ALL_BUSY);
} }
unusedSem = LOS_DL_LIST_FIRST(&g_unusedSemList); unusedSem = LOS_DL_LIST_FIRST(&g_unusedSemList);//拿第一个出来创建
LOS_ListDelete(unusedSem); LOS_ListDelete(unusedSem);//从空闲链表上摘除
semCreated = GET_SEM_LIST(unusedSem); semCreated = GET_SEM_LIST(unusedSem);//通过semList挂到链表上的,这里也要通过它把LosSemCB头查到. 进程,线程等结构体也都是这么干的.
semCreated->semCount = count; semCreated->semCount = count;//设置数量
semCreated->semStat = OS_SEM_USED; semCreated->semStat = OS_SEM_USED;//设置可用状态
semCreated->maxSemCount = maxCount; semCreated->maxSemCount = maxCount;//设置最大信号数量
LOS_ListInit(&semCreated->semList); LOS_ListInit(&semCreated->semList);//初始化链表,后续阻塞任务通过task->pendList挂到semList链表上,就知道哪些任务在等它了.
*semHandle = semCreated->semID; *semHandle = semCreated->semID;//参数带走 semID
OsSemDbgUpdateHook(semCreated->semID, OsCurrTaskGet()->taskEntry, count); OsSemDbgUpdateHook(semCreated->semID, OsCurrTaskGet()->taskEntry, count);
...@@ -140,7 +140,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_BinarySemCreate(UINT16 count, UINT32 *semHandle ...@@ -140,7 +140,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_BinarySemCreate(UINT16 count, UINT32 *semHandle
{ {
return OsSemCreate(count, OS_SEM_BINARY_COUNT_MAX, semHandle); return OsSemCreate(count, OS_SEM_BINARY_COUNT_MAX, semHandle);
} }
//删除信号量,参数就是 semID
LITE_OS_SEC_TEXT_INIT UINT32 LOS_SemDelete(UINT32 semHandle) LITE_OS_SEC_TEXT_INIT UINT32 LOS_SemDelete(UINT32 semHandle)
{ {
UINT32 intSave; UINT32 intSave;
...@@ -152,23 +152,23 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_SemDelete(UINT32 semHandle) ...@@ -152,23 +152,23 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_SemDelete(UINT32 semHandle)
OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_INVALID); OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_INVALID);
} }
semDeleted = GET_SEM(semHandle); semDeleted = GET_SEM(semHandle);//通过ID拿到信号量实体
SCHEDULER_LOCK(intSave); SCHEDULER_LOCK(intSave);
if ((semDeleted->semStat == OS_SEM_UNUSED) || (semDeleted->semID != semHandle)) { if ((semDeleted->semStat == OS_SEM_UNUSED) || (semDeleted->semID != semHandle)) {//参数判断
SCHEDULER_UNLOCK(intSave); SCHEDULER_UNLOCK(intSave);
OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_INVALID); OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_INVALID);
} }
if (!LOS_ListEmpty(&semDeleted->semList)) { if (!LOS_ListEmpty(&semDeleted->semList)) {//当前还有任务挂在这个信号上面,当然不能删除
SCHEDULER_UNLOCK(intSave); SCHEDULER_UNLOCK(intSave);
OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_PENDED); OS_GOTO_ERR_HANDLER(LOS_ERRNO_SEM_PENDED);//这个宏很有意思,里面goto到ERR_HANDLER
} }
LOS_ListTailInsert(&g_unusedSemList, &semDeleted->semList); LOS_ListTailInsert(&g_unusedSemList, &semDeleted->semList);//通过semList从尾部插入空闲链表
semDeleted->semStat = OS_SEM_UNUSED; semDeleted->semStat = OS_SEM_UNUSED;//状态变成了未使用
semDeleted->semID = SET_SEM_ID(GET_SEM_COUNT(semDeleted->semID) + 1, GET_SEM_INDEX(semDeleted->semID)); semDeleted->semID = SET_SEM_ID(GET_SEM_COUNT(semDeleted->semID) + 1, GET_SEM_INDEX(semDeleted->semID));//设置ID
OsSemDbgUpdateHook(semDeleted->semID, NULL, 0); OsSemDbgUpdateHook(semDeleted->semID, NULL, 0);
...@@ -178,11 +178,11 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_SemDelete(UINT32 semHandle) ...@@ -178,11 +178,11 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_SemDelete(UINT32 semHandle)
ERR_HANDLER: ERR_HANDLER:
OS_RETURN_ERROR_P2(errLine, errNo); OS_RETURN_ERROR_P2(errLine, errNo);
} }
//挂起信号
LITE_OS_SEC_TEXT UINT32 LOS_SemPend(UINT32 semHandle, UINT32 timeout) LITE_OS_SEC_TEXT UINT32 LOS_SemPend(UINT32 semHandle, UINT32 timeout)
{ {
UINT32 intSave; UINT32 intSave;
LosSemCB *semPended = GET_SEM(semHandle); LosSemCB *semPended = GET_SEM(semHandle);//通过ID拿到信号体
UINT32 retErr = LOS_OK; UINT32 retErr = LOS_OK;
LosTaskCB *runTask = NULL; LosTaskCB *runTask = NULL;
...@@ -196,7 +196,7 @@ LITE_OS_SEC_TEXT UINT32 LOS_SemPend(UINT32 semHandle, UINT32 timeout) ...@@ -196,7 +196,7 @@ LITE_OS_SEC_TEXT UINT32 LOS_SemPend(UINT32 semHandle, UINT32 timeout)
return LOS_ERRNO_SEM_PEND_INTERR; return LOS_ERRNO_SEM_PEND_INTERR;
} }
runTask = OsCurrTaskGet(); runTask = OsCurrTaskGet();//获取当前任务
if (runTask->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) { if (runTask->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {
OsBackTrace(); OsBackTrace();
return LOS_ERRNO_SEM_PEND_IN_SYSTEM_TASK; return LOS_ERRNO_SEM_PEND_IN_SYSTEM_TASK;
...@@ -212,24 +212,24 @@ LITE_OS_SEC_TEXT UINT32 LOS_SemPend(UINT32 semHandle, UINT32 timeout) ...@@ -212,24 +212,24 @@ LITE_OS_SEC_TEXT UINT32 LOS_SemPend(UINT32 semHandle, UINT32 timeout)
/* Update the operate time, no matter the actual Pend success or not */ /* Update the operate time, no matter the actual Pend success or not */
OsSemDbgTimeUpdateHook(semHandle); OsSemDbgTimeUpdateHook(semHandle);
if (semPended->semCount > 0) { if (semPended->semCount > 0) {//还有资源可用,返回肯定得成功,semCount=0时代表没资源了,task会必须去睡眠了
semPended->semCount--; semPended->semCount--;//资源少了一个
goto OUT; goto OUT;//注意这里 retErr = LOS_OK ,所以返回是OK的
} else if (!timeout) { } else if (!timeout) {
retErr = LOS_ERRNO_SEM_UNAVAILABLE; retErr = LOS_ERRNO_SEM_UNAVAILABLE;
goto OUT; goto OUT;
} }
if (!OsPreemptableInSched()) { if (!OsPreemptableInSched()) {//不能申请调度 (不能调度的原因是因为没有持有调度任务自旋锁)
PRINT_ERR("!!!LOS_ERRNO_SEM_PEND_IN_LOCK!!!\n"); PRINT_ERR("!!!LOS_ERRNO_SEM_PEND_IN_LOCK!!!\n");
OsBackTrace(); OsBackTrace();
retErr = LOS_ERRNO_SEM_PEND_IN_LOCK; retErr = LOS_ERRNO_SEM_PEND_IN_LOCK;
goto OUT; goto OUT;
} }
runTask->taskSem = (VOID *)semPended; runTask->taskSem = (VOID *)semPended;//标记当前任务在等这个信号量
retErr = OsTaskWait(&semPended->semList, timeout, TRUE); retErr = OsTaskWait(&semPended->semList, timeout, TRUE);//任务进入等待状态,当前任务会挂到semList上,并在其中切换任务上下文
if (retErr == LOS_ERRNO_TSK_TIMEOUT) { if (retErr == LOS_ERRNO_TSK_TIMEOUT) {//注意:这里是涉及到task切换的,把自己挂起,唤醒其他task
runTask->taskSem = NULL; runTask->taskSem = NULL;
retErr = LOS_ERRNO_SEM_TIMEOUT; retErr = LOS_ERRNO_SEM_TIMEOUT;
} }
...@@ -238,7 +238,7 @@ OUT: ...@@ -238,7 +238,7 @@ OUT:
SCHEDULER_UNLOCK(intSave); SCHEDULER_UNLOCK(intSave);
return retErr; return retErr;
} }
//释放信号
LITE_OS_SEC_TEXT UINT32 OsSemPostUnsafe(UINT32 semHandle, BOOL *needSched) LITE_OS_SEC_TEXT UINT32 OsSemPostUnsafe(UINT32 semHandle, BOOL *needSched)
{ {
LosSemCB *semPosted = NULL; LosSemCB *semPosted = NULL;
...@@ -256,18 +256,18 @@ LITE_OS_SEC_TEXT UINT32 OsSemPostUnsafe(UINT32 semHandle, BOOL *needSched) ...@@ -256,18 +256,18 @@ LITE_OS_SEC_TEXT UINT32 OsSemPostUnsafe(UINT32 semHandle, BOOL *needSched)
/* Update the operate time, no matter the actual Post success or not */ /* Update the operate time, no matter the actual Post success or not */
OsSemDbgTimeUpdateHook(semHandle); OsSemDbgTimeUpdateHook(semHandle);
if (semPosted->semCount == OS_SEM_COUNT_MAX) { if (semPosted->semCount == OS_SEM_COUNT_MAX) {//当前信号资源不能大于最大资源量
return LOS_ERRNO_SEM_OVERFLOW; return LOS_ERRNO_SEM_OVERFLOW;
} }
if (!LOS_ListEmpty(&semPosted->semList)) { if (!LOS_ListEmpty(&semPosted->semList)) {//当前有任务挂在semList上,要去唤醒任务
resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(semPosted->semList))); resumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(semPosted->semList)));//semList上面挂的都是task->pendlist节点,取第一个task下来唤醒
resumedTask->taskSem = NULL; resumedTask->taskSem = NULL;//任务不用等信号了,重新变成NULL值
OsTaskWake(resumedTask); OsTaskWake(resumedTask);//唤醒任务,注意resumedTask一定不是当前任务,OsTaskWake里面并不会自己切换任务上下文,只是设置状态
if (needSched != NULL) { if (needSched != NULL) {//参数不为空,就返回需要调度的标签
*needSched = TRUE; *needSched = TRUE;//TRUE代表需要调度
} }
} else { } else {//当前没有任务挂在semList上,
semPosted->semCount++; semPosted->semCount++;//信号资源多一个
} }
return LOS_OK; return LOS_OK;
...@@ -282,9 +282,9 @@ LITE_OS_SEC_TEXT UINT32 LOS_SemPost(UINT32 semHandle) ...@@ -282,9 +282,9 @@ LITE_OS_SEC_TEXT UINT32 LOS_SemPost(UINT32 semHandle)
SCHEDULER_LOCK(intSave); SCHEDULER_LOCK(intSave);
ret = OsSemPostUnsafe(semHandle, &needSched); ret = OsSemPostUnsafe(semHandle, &needSched);
SCHEDULER_UNLOCK(intSave); SCHEDULER_UNLOCK(intSave);
if (needSched) { if (needSched) {//需要调度的情况
LOS_MpSchedule(OS_MP_CPU_ALL); LOS_MpSchedule(OS_MP_CPU_ALL);//向所有CPU发送调度指令
LOS_Schedule(); LOS_Schedule();////发起调度
} }
return ret; return ret;
......
...@@ -240,7 +240,7 @@ extern UINT32 __heap_end; // 堆区结束地址 ...@@ -240,7 +240,7 @@ extern UINT32 __heap_end; // 堆区结束地址
* Configuration item for semaphore module tailoring * Configuration item for semaphore module tailoring
*/ */
#ifndef LOSCFG_BASE_IPC_SEM #ifndef LOSCFG_BASE_IPC_SEM
#define LOSCFG_BASE_IPC_SEM YES #define LOSCFG_BASE_IPC_SEM YES //信号量支持
#endif #endif
/** /**
...@@ -248,7 +248,7 @@ extern UINT32 __heap_end; // 堆区结束地址 ...@@ -248,7 +248,7 @@ extern UINT32 __heap_end; // 堆区结束地址
* Maximum supported number of semaphores * Maximum supported number of semaphores
*/ */
#ifndef LOSCFG_BASE_IPC_SEM_LIMIT #ifndef LOSCFG_BASE_IPC_SEM_LIMIT
#define LOSCFG_BASE_IPC_SEM_LIMIT 1024 #define LOSCFG_BASE_IPC_SEM_LIMIT 1024 //信号量的最大个数
#endif #endif
/****************************** mutex module configuration ******************************/ /****************************** mutex module configuration ******************************/
...@@ -257,7 +257,7 @@ extern UINT32 __heap_end; // 堆区结束地址 ...@@ -257,7 +257,7 @@ extern UINT32 __heap_end; // 堆区结束地址
* Configuration item for mutex module tailoring * Configuration item for mutex module tailoring
*/ */
#ifndef LOSCFG_BASE_IPC_MUX #ifndef LOSCFG_BASE_IPC_MUX
#define LOSCFG_BASE_IPC_MUX YES #define LOSCFG_BASE_IPC_MUX YES //互斥量的支持
#endif #endif
/****************************** Queue module configuration ********************************/ /****************************** Queue module configuration ********************************/
...@@ -266,7 +266,7 @@ extern UINT32 __heap_end; // 堆区结束地址 ...@@ -266,7 +266,7 @@ extern UINT32 __heap_end; // 堆区结束地址
* Configuration item for queue module tailoring * Configuration item for queue module tailoring
*/ */
#ifndef LOSCFG_BASE_IPC_QUEUE #ifndef LOSCFG_BASE_IPC_QUEUE
#define LOSCFG_BASE_IPC_QUEUE YES #define LOSCFG_BASE_IPC_QUEUE YES //是否支持IPC队列?
#endif #endif
/** /**
...@@ -274,17 +274,17 @@ extern UINT32 __heap_end; // 堆区结束地址 ...@@ -274,17 +274,17 @@ extern UINT32 __heap_end; // 堆区结束地址
* Maximum supported number of queues rather than the number of usable queues * Maximum supported number of queues rather than the number of usable queues
*/ */
#ifndef LOSCFG_BASE_IPC_QUEUE_LIMIT #ifndef LOSCFG_BASE_IPC_QUEUE_LIMIT
#define LOSCFG_BASE_IPC_QUEUE_LIMIT 1024 #define LOSCFG_BASE_IPC_QUEUE_LIMIT 1024 //队列个数
#endif #endif
/****************************** Software timer module configuration **************************/ /****************************** Software timer module configuration **************************/
#if (LOSCFG_BASE_IPC_QUEUE == YES) #if (LOSCFG_BASE_IPC_QUEUE == YES) //软时钟模块需打开IPC队列
/** /**
* @ingroup los_config * @ingroup los_config
* Configuration item for software timer module tailoring * Configuration item for software timer module tailoring
*/ */
#ifndef LOSCFG_BASE_CORE_SWTMR #ifndef LOSCFG_BASE_CORE_SWTMR
#define LOSCFG_BASE_CORE_SWTMR YES #define LOSCFG_BASE_CORE_SWTMR YES //是否支持软时钟?
#endif #endif
/** /**
......
...@@ -190,7 +190,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_SpinUnlock(SPIN_LOCK_S *lock) ...@@ -190,7 +190,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_SpinUnlock(SPIN_LOCK_S *lock)
* @see LOS_SpinLock * @see LOS_SpinLock
*/ */
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_SpinLockSave(SPIN_LOCK_S *lock, UINT32 *intSave) LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_SpinLockSave(SPIN_LOCK_S *lock, UINT32 *intSave)
{ {//自旋锁是不切换任务上下文的,忙等状态.锁的是细颗粒的操作,代码量小,运行时间端的临界区
*intSave = LOS_IntLock(); *intSave = LOS_IntLock();
LOS_SpinLock(lock); LOS_SpinLock(lock);
} }
...@@ -288,7 +288,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_SpinUnlock(SPIN_LOCK_S *lock) ...@@ -288,7 +288,7 @@ LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_SpinUnlock(SPIN_LOCK_S *lock)
} }
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_SpinLockSave(SPIN_LOCK_S *lock, UINT32 *intSave) LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_SpinLockSave(SPIN_LOCK_S *lock, UINT32 *intSave)
{ {//自旋锁是不切换任务上下文的,忙等状态.锁的是细颗粒的操作,代码量小,运行时间端的临界区
(VOID)lock; (VOID)lock;
*intSave = LOS_IntLock(); *intSave = LOS_IntLock();
} }
......
#ifndef _NOTE_IPC_H
#define _NOTE_IPC_H
/****************************************************************
信号量是为了解决task的资源同步问题,有多少资源就设多大的资源最大值
信号量机制:
以一个停车场的运作为例。假设停车场只有三个车位,一开始三个车位都是空的。这时如果同时来了五辆车,
看门人允许其中三辆直接进入,然后放下车拦,剩下的车则必须在入口等待,此后来的车也都不得不在入口处等待。
这时,有一辆车离开停车场,看门人得知后,打开车拦,放入外面的一辆进去,如果又离开两辆,则又可以放入两辆,如此往复。
信号量的规则:
如果当前资源计数器大于0,那么信号量处于触发状态
如果当前资源计数器等于0,那么信号量处于未触发状态
系统绝对不会让当前资源计数器变为负数
当前资源计数器决定不会大于最大资源计数
最大资源计数,表示可以控件的最大资源数量
当前资源计数,表示当前可用资源的数量
****************************************************************/
#endif
git add -A git add -A
git commit -m '加入了wiki的支持,后续四大码仓wiki也同步推 git commit -m '开始对信号量这块代码进行注释,信号量的出现为了解决task的同步问题
鸿蒙内核源码分析系列 【 CSDN | OSCHINA | WIKI 】 鸿蒙内核源码分析系列 【 CSDN | OSCHINA | WIKI 】
鸿蒙内核源码注释中文版 【 CSDN仓 | Gitee仓 | Github仓 | Coding仓 】四大仓库每日同步更新代码和wiki 鸿蒙内核源码注释中文版 【 CSDN仓 | Gitee仓 | Github仓 | Coding仓 】四大仓库每日同步更新代码和wiki
给鸿蒙内核源码逐行加上中文注解,详细阐述设计细节, 助你快速精读 HarmonyOS 内核源码, 掌握整个鸿蒙内核运行机制.' 给鸿蒙内核源码逐行加上中文注解,详细阐述设计细节, 助你快速精读 HarmonyOS 内核源码, 掌握整个鸿蒙内核运行机制.'
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册