diff --git a/src/kernel_liteos_a/kernel/base/ipc/los_event.c b/src/kernel_liteos_a/kernel/base/ipc/los_event.c index 1503c7fb..ccea383b 100644 --- a/src/kernel_liteos_a/kernel/base/ipc/los_event.c +++ b/src/kernel_liteos_a/kernel/base/ipc/los_event.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. - * Copyright (c) 2020-2022 Huawei Device Co., Ltd. All rights reserved. + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -39,8 +39,8 @@ #ifdef LOSCFG_BASE_CORE_SWTMR_ENABLE #include "los_exc.h" #endif -/* -*/ + +/// 初始化一个事件控制块 LITE_OS_SEC_TEXT_INIT UINT32 LOS_EventInit(PEVENT_CB_S eventCB) { UINT32 intSave; @@ -49,14 +49,14 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_EventInit(PEVENT_CB_S eventCB) return LOS_ERRNO_EVENT_PTR_NULL; } - intSave = LOS_IntLock(); - eventCB->uwEventID = 0; - LOS_ListInit(&eventCB->stEventList); - LOS_IntRestore(intSave); + intSave = LOS_IntLock();//锁中断 + eventCB->uwEventID = 0;//事件类型初始化 + LOS_ListInit(&eventCB->stEventList);//事件链表初始化 + LOS_IntRestore(intSave);//恢复中断 OsHookCall(LOS_HOOK_TYPE_EVENT_INIT, eventCB); return LOS_OK; } - +///事件参数检查 LITE_OS_SEC_TEXT STATIC UINT32 OsEventParamCheck(const VOID *ptr, UINT32 eventMask, UINT32 mode) { if (ptr == NULL) { @@ -78,52 +78,53 @@ LITE_OS_SEC_TEXT STATIC UINT32 OsEventParamCheck(const VOID *ptr, UINT32 eventMa } return LOS_OK; } - +///根据用户传入的事件值、事件掩码及校验模式,返回用户传入的事件是否符合预期 LITE_OS_SEC_TEXT UINT32 OsEventPoll(UINT32 *eventID, UINT32 eventMask, UINT32 mode) { UINT32 ret = 0; - LOS_ASSERT(OsIntLocked()); - LOS_ASSERT(LOS_SpinHeld(&g_taskSpin)); + LOS_ASSERT(OsIntLocked());//断言不允许中断了 + LOS_ASSERT(LOS_SpinHeld(&g_taskSpin));//任务自旋锁 - if (mode & LOS_WAITMODE_OR) { + if (mode & LOS_WAITMODE_OR) {//如果模式是读取掩码中任意事件 if ((*eventID & eventMask) != 0) { ret = *eventID & eventMask; } - } else { - if ((eventMask != 0) && (eventMask == (*eventID & eventMask))) { + } else {//等待全部事件发生 + if ((eventMask != 0) && (eventMask == (*eventID & eventMask))) {//必须满足全部事件发生 ret = *eventID & eventMask; } } - if (ret && (mode & LOS_WAITMODE_CLR)) { + if (ret && (mode & LOS_WAITMODE_CLR)) {//读取完成后清除事件 *eventID = *eventID & ~ret; } return ret; } - +///检查读事件 LITE_OS_SEC_TEXT STATIC UINT32 OsEventReadCheck(const PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode) { UINT32 ret; LosTaskCB *runTask = NULL; - ret = OsEventParamCheck(eventCB, eventMask, mode); + + ret = OsEventParamCheck(eventCB, eventMask, mode);//事件参数检查 if (ret != LOS_OK) { return ret; } - if (OS_INT_ACTIVE) { - return LOS_ERRNO_EVENT_READ_IN_INTERRUPT; + if (OS_INT_ACTIVE) {//中断正在进行 + return LOS_ERRNO_EVENT_READ_IN_INTERRUPT;//不能在中断发送时读事件 } - runTask = OsCurrTaskGet(); - if (runTask->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) { + runTask = OsCurrTaskGet();//获取当前任务 + if (runTask->taskStatus & OS_TASK_FLAG_SYSTEM_TASK) {//任务属于系统任务 OsBackTrace(); - return LOS_ERRNO_EVENT_READ_IN_SYSTEM_TASK; + return LOS_ERRNO_EVENT_READ_IN_SYSTEM_TASK;//不能在系统任务中读取事件 } return LOS_OK; } - +/// 读取指定事件类型的实现函数,超时时间为相对时间:单位为Tick LITE_OS_SEC_TEXT STATIC UINT32 OsEventReadImp(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout, BOOL once) { @@ -132,57 +133,57 @@ LITE_OS_SEC_TEXT STATIC UINT32 OsEventReadImp(PEVENT_CB_S eventCB, UINT32 eventM OsHookCall(LOS_HOOK_TYPE_EVENT_READ, eventCB, eventMask, mode, timeout); if (once == FALSE) { - ret = OsEventPoll(&eventCB->uwEventID, eventMask, mode); + ret = OsEventPoll(&eventCB->uwEventID, eventMask, mode);//检测事件是否符合预期 } - if (ret == 0) { - if (timeout == 0) { + if (ret == 0) {//不符合预期时 + if (timeout == 0) {//不等待的情况 return ret; } - if (!OsPreemptableInSched()) { + if (!OsPreemptableInSched()) {//不能抢占式调度 return LOS_ERRNO_EVENT_READ_IN_LOCK; } - runTask->eventMask = eventMask; - runTask->eventMode = mode; - runTask->taskEvent = eventCB; - OsTaskWaitSetPendMask(OS_TASK_WAIT_EVENT, eventMask, timeout); + runTask->eventMask = eventMask; //等待事件 + runTask->eventMode = mode; //事件模式 + runTask->taskEvent = eventCB; //事件控制块 + OsTaskWaitSetPendMask(OS_TASK_WAIT_EVENT, eventMask, timeout);//任务进入等待状态,等待事件的到来并设置时长和掩码 ret = runTask->ops->wait(runTask, &eventCB->stEventList, timeout); if (ret == LOS_ERRNO_TSK_TIMEOUT) { return LOS_ERRNO_EVENT_READ_TIMEOUT; } - ret = OsEventPoll(&eventCB->uwEventID, eventMask, mode); + ret = OsEventPoll(&eventCB->uwEventID, eventMask, mode);//检测事件是否符合预期 } return ret; } - +///读取指定事件类型,超时时间为相对时间:单位为Tick LITE_OS_SEC_TEXT STATIC UINT32 OsEventRead(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout, BOOL once) { UINT32 ret; UINT32 intSave; - ret = OsEventReadCheck(eventCB, eventMask, mode); + ret = OsEventReadCheck(eventCB, eventMask, mode);//读取事件检查 if (ret != LOS_OK) { return ret; } SCHEDULER_LOCK(intSave); - ret = OsEventReadImp(eventCB, eventMask, mode, timeout, once); + ret = OsEventReadImp(eventCB, eventMask, mode, timeout, once);//读事件实现函数 SCHEDULER_UNLOCK(intSave); return ret; } - +///事件恢复操作 LITE_OS_SEC_TEXT STATIC UINT8 OsEventResume(LosTaskCB *resumedTask, const PEVENT_CB_S eventCB, UINT32 events) { - UINT8 exitFlag = 0; + UINT8 exitFlag = 0;//是否唤醒 if (((resumedTask->eventMode & LOS_WAITMODE_OR) && ((resumedTask->eventMask & events) != 0)) || ((resumedTask->eventMode & LOS_WAITMODE_AND) && - ((resumedTask->eventMask & eventCB->uwEventID) == resumedTask->eventMask))) { - exitFlag = 1; + ((resumedTask->eventMask & eventCB->uwEventID) == resumedTask->eventMask))) {//逻辑与 和 逻辑或 的处理 + exitFlag = 1; resumedTask->taskEvent = NULL; OsTaskWakeClearPendMask(resumedTask); @@ -191,33 +192,33 @@ LITE_OS_SEC_TEXT STATIC UINT8 OsEventResume(LosTaskCB *resumedTask, const PEVENT return exitFlag; } - +///以不安全的方式写事件 LITE_OS_SEC_TEXT VOID OsEventWriteUnsafe(PEVENT_CB_S eventCB, UINT32 events, BOOL once, UINT8 *exitFlag) { LosTaskCB *resumedTask = NULL; LosTaskCB *nextTask = NULL; BOOL schedFlag = FALSE; OsHookCall(LOS_HOOK_TYPE_EVENT_WRITE, eventCB, events); - eventCB->uwEventID |= events; - if (!LOS_ListEmpty(&eventCB->stEventList)) { + eventCB->uwEventID |= events;//对应位贴上标签 + if (!LOS_ListEmpty(&eventCB->stEventList)) {//等待事件链表判断,处理等待事件的任务 for (resumedTask = LOS_DL_LIST_ENTRY((&eventCB->stEventList)->pstNext, LosTaskCB, pendList); - &resumedTask->pendList != &eventCB->stEventList;) { - nextTask = LOS_DL_LIST_ENTRY(resumedTask->pendList.pstNext, LosTaskCB, pendList); - if (OsEventResume(resumedTask, eventCB, events)) { - schedFlag = TRUE; + &resumedTask->pendList != &eventCB->stEventList;) {//循环获取任务链表 + nextTask = LOS_DL_LIST_ENTRY(resumedTask->pendList.pstNext, LosTaskCB, pendList);//获取任务实体 + if (OsEventResume(resumedTask, eventCB, events)) {//是否恢复任务 + schedFlag = TRUE;//任务已加至就绪队列,申请发生一次调度 } - if (once == TRUE) { - break; + if (once == TRUE) {//是否只处理一次任务 + break;//退出循环 } - resumedTask = nextTask; + resumedTask = nextTask;//检查链表中下一个任务 } } - if ((exitFlag != NULL) && (schedFlag == TRUE)) { + if ((exitFlag != NULL) && (schedFlag == TRUE)) {//是否让外面调度 *exitFlag = 1; } } - +///写入事件 LITE_OS_SEC_TEXT STATIC UINT32 OsEventWrite(PEVENT_CB_S eventCB, UINT32 events, BOOL once) { UINT32 intSave; @@ -231,54 +232,54 @@ LITE_OS_SEC_TEXT STATIC UINT32 OsEventWrite(PEVENT_CB_S eventCB, UINT32 events, return LOS_ERRNO_EVENT_SETBIT_INVALID; } - SCHEDULER_LOCK(intSave); - OsEventWriteUnsafe(eventCB, events, once, &exitFlag); - SCHEDULER_UNLOCK(intSave); + SCHEDULER_LOCK(intSave); //禁止调度 + OsEventWriteUnsafe(eventCB, events, once, &exitFlag);//写入事件 + SCHEDULER_UNLOCK(intSave); //允许调度 - if (exitFlag == 1) { - LOS_MpSchedule(OS_MP_CPU_ALL); - LOS_Schedule(); + if (exitFlag == 1) { //需要发生调度 + LOS_MpSchedule(OS_MP_CPU_ALL);//通知所有CPU调度 + LOS_Schedule();//执行调度 } return LOS_OK; } - +///根据用户传入的事件值、事件掩码及校验模式,返回用户传入的事件是否符合预期 LITE_OS_SEC_TEXT UINT32 LOS_EventPoll(UINT32 *eventID, UINT32 eventMask, UINT32 mode) { UINT32 ret; UINT32 intSave; - + //事件参数检查 ret = OsEventParamCheck((VOID *)eventID, eventMask, mode); if (ret != LOS_OK) { return ret; } - SCHEDULER_LOCK(intSave); + SCHEDULER_LOCK(intSave);//申请任务自旋锁 ret = OsEventPoll(eventID, eventMask, mode); SCHEDULER_UNLOCK(intSave); return ret; } - +///读取指定事件类型,超时时间为相对时间:单位为Tick LITE_OS_SEC_TEXT UINT32 LOS_EventRead(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout) { return OsEventRead(eventCB, eventMask, mode, timeout, FALSE); } - +///写指定的事件类型 LITE_OS_SEC_TEXT UINT32 LOS_EventWrite(PEVENT_CB_S eventCB, UINT32 events) { return OsEventWrite(eventCB, events, FALSE); } - +///只读一次事件 LITE_OS_SEC_TEXT_MINOR UINT32 OsEventReadOnce(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout) { return OsEventRead(eventCB, eventMask, mode, timeout, TRUE); } - +///只写一次事件 LITE_OS_SEC_TEXT_MINOR UINT32 OsEventWriteOnce(PEVENT_CB_S eventCB, UINT32 events) { return OsEventWrite(eventCB, events, TRUE); } - +///销毁指定的事件控制块 LITE_OS_SEC_TEXT_INIT UINT32 LOS_EventDestroy(PEVENT_CB_S eventCB) { UINT32 intSave; @@ -299,7 +300,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_EventDestroy(PEVENT_CB_S eventCB) OsHookCall(LOS_HOOK_TYPE_EVENT_DESTROY, eventCB); return LOS_OK; } - +///清除指定的事件类型 LITE_OS_SEC_TEXT_MINOR UINT32 LOS_EventClear(PEVENT_CB_S eventCB, UINT32 eventMask) { UINT32 intSave; @@ -314,7 +315,7 @@ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_EventClear(PEVENT_CB_S eventCB, UINT32 eventMa return LOS_OK; } - +///有条件式读事件 #ifdef LOSCFG_COMPAT_POSIX LITE_OS_SEC_TEXT UINT32 OsEventReadWithCond(const EventCond *cond, PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout) diff --git a/src/kernel_liteos_a/kernel/base/ipc/los_futex.c b/src/kernel_liteos_a/kernel/base/ipc/los_futex.c index 384bb483..ea69c554 100644 --- a/src/kernel_liteos_a/kernel/base/ipc/los_futex.c +++ b/src/kernel_liteos_a/kernel/base/ipc/los_futex.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. - * Copyright (c) 2020-2022 Huawei Device Co., Ltd. All rights reserved. + * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -43,28 +43,30 @@ #ifdef LOSCFG_KERNEL_VM -#define OS_FUTEX_FROM_FUTEXLIST(ptr) LOS_DL_LIST_ENTRY(ptr, FutexNode, futexList) -#define OS_FUTEX_FROM_QUEUELIST(ptr) LOS_DL_LIST_ENTRY(ptr, FutexNode, queueList) -#define OS_FUTEX_KEY_BASE USER_ASPACE_BASE -#define OS_FUTEX_KEY_MAX (USER_ASPACE_BASE + USER_ASPACE_SIZE) +#define OS_FUTEX_FROM_FUTEXLIST(ptr) LOS_DL_LIST_ENTRY(ptr, FutexNode, futexList) // 通过快锁节点找到结构体 +#define OS_FUTEX_FROM_QUEUELIST(ptr) LOS_DL_LIST_ENTRY(ptr, FutexNode, queueList) // 通过队列节点找到结构体 +#define OS_FUTEX_KEY_BASE USER_ASPACE_BASE ///< 进程用户空间基址 +#define OS_FUTEX_KEY_MAX (USER_ASPACE_BASE + USER_ASPACE_SIZE) ///< 进程用户空间尾址 /* private: 0~63 hash index_num * shared: 64~79 hash index_num */ -#define FUTEX_INDEX_PRIVATE_MAX 64 -#define FUTEX_INDEX_SHARED_MAX 16 -#define FUTEX_INDEX_MAX (FUTEX_INDEX_PRIVATE_MAX + FUTEX_INDEX_SHARED_MAX) +#define FUTEX_INDEX_PRIVATE_MAX 64 ///< 0~63号桶用于存放私有锁(以虚拟地址进行哈希),同一进程不同线程共享futex变量,表明变量在进程地址空间中的位置 +///< 它告诉内核,这个futex是进程专有的,不可以与其他进程共享。它仅仅用作同一进程的线程间同步。 +#define FUTEX_INDEX_SHARED_MAX 16 ///< 64~79号桶用于存放共享锁(以物理地址进行哈希),不同进程间通过文件共享futex变量,表明该变量在文件中的位置 +#define FUTEX_INDEX_MAX (FUTEX_INDEX_PRIVATE_MAX + FUTEX_INDEX_SHARED_MAX) ///< 80个哈希桶 -#define FUTEX_INDEX_SHARED_POS FUTEX_INDEX_PRIVATE_MAX +#define FUTEX_INDEX_SHARED_POS FUTEX_INDEX_PRIVATE_MAX ///< 共享锁开始位置 #define FUTEX_HASH_PRIVATE_MASK (FUTEX_INDEX_PRIVATE_MAX - 1) #define FUTEX_HASH_SHARED_MASK (FUTEX_INDEX_SHARED_MAX - 1) - +/// 单独哈希桶,上面挂了一个个 FutexNode typedef struct { - LosMux listLock; - LOS_DL_LIST lockList; + LosMux listLock;///< 内核操作lockList的互斥锁 + LOS_DL_LIST lockList;///< 用于挂载 FutexNode (Fast userspace mutex,用户态快速互斥锁) } FutexHash; -FutexHash g_futexHash[FUTEX_INDEX_MAX]; +FutexHash g_futexHash[FUTEX_INDEX_MAX];///< 80个哈希桶 +/// 对互斥锁封装 STATIC INT32 OsFutexLock(LosMux *lock) { UINT32 ret = LOS_MuxLock(lock, LOS_WAIT_FOREVER); @@ -84,15 +86,15 @@ STATIC INT32 OsFutexUnlock(LosMux *lock) } return LOS_OK; } - +///< 初始化Futex(Fast userspace mutex,用户态快速互斥锁)模块 UINT32 OsFutexInit(VOID) { INT32 count; UINT32 ret; - + // 初始化 80个哈希桶 for (count = 0; count < FUTEX_INDEX_MAX; count++) { - LOS_ListInit(&g_futexHash[count].lockList); - ret = LOS_MuxInit(&(g_futexHash[count].listLock), NULL); + LOS_ListInit(&g_futexHash[count].lockList); // 初始化双向链表,上面挂 FutexNode + ret = LOS_MuxInit(&(g_futexHash[count].listLock), NULL);//初始化互斥锁 if (ret) { return ret; } @@ -101,7 +103,7 @@ UINT32 OsFutexInit(VOID) return LOS_OK; } -LOS_MODULE_INIT(OsFutexInit, LOS_INIT_LEVEL_KMOD_EXTENDED); +LOS_MODULE_INIT(OsFutexInit, LOS_INIT_LEVEL_KMOD_EXTENDED);///< 注册Futex模块 #ifdef LOS_FUTEX_DEBUG STATIC VOID OsFutexShowTaskNodeAttr(const LOS_DL_LIST *futexList) @@ -152,63 +154,63 @@ VOID OsFutexHashShow(VOID) } } #endif - +/// 通过用户空间地址获取哈希key STATIC INLINE UINTPTR OsFutexFlagsToKey(const UINT32 *userVaddr, const UINT32 flags) { UINTPTR futexKey; if (flags & FUTEX_PRIVATE) { - futexKey = (UINTPTR)userVaddr; + futexKey = (UINTPTR)userVaddr;//私有锁(以虚拟地址进行哈希) } else { - futexKey = (UINTPTR)LOS_PaddrQuery((UINT32 *)userVaddr); + futexKey = (UINTPTR)LOS_PaddrQuery((UINT32 *)userVaddr);//共享锁(以物理地址进行哈希) } return futexKey; } - +/// 通过哈希key获取索引 STATIC INLINE UINT32 OsFutexKeyToIndex(const UINTPTR futexKey, const UINT32 flags) { - UINT32 index = LOS_HashFNV32aBuf(&futexKey, sizeof(UINTPTR), FNV1_32A_INIT); + UINT32 index = LOS_HashFNV32aBuf(&futexKey, sizeof(UINTPTR), FNV1_32A_INIT);//获取哈希桶索引 if (flags & FUTEX_PRIVATE) { - index &= FUTEX_HASH_PRIVATE_MASK; + index &= FUTEX_HASH_PRIVATE_MASK;//将index锁定在 0 ~ 63号 } else { index &= FUTEX_HASH_SHARED_MASK; - index += FUTEX_INDEX_SHARED_POS; + index += FUTEX_INDEX_SHARED_POS;//共享锁索引,将index锁定在 64 ~ 79号 } return index; } - +/// 设置快锁哈希key STATIC INLINE VOID OsFutexSetKey(UINTPTR futexKey, UINT32 flags, FutexNode *node) { - node->key = futexKey; - node->index = OsFutexKeyToIndex(futexKey, flags); - node->pid = (flags & FUTEX_PRIVATE) ? LOS_GetCurrProcessID() : OS_INVALID; + node->key = futexKey;//哈希key + node->index = OsFutexKeyToIndex(futexKey, flags);//哈希桶索引 + node->pid = (flags & FUTEX_PRIVATE) ? LOS_GetCurrProcessID() : OS_INVALID;//获取进程ID,共享快锁时 快锁节点没有进程ID } - +//析构参数节点 STATIC INLINE VOID OsFutexDeinitFutexNode(FutexNode *node) { node->index = OS_INVALID_VALUE; node->pid = 0; LOS_ListDelete(&node->queueList); } - +/// 新旧两个节点交换 futexList 位置 STATIC INLINE VOID OsFutexReplaceQueueListHeadNode(FutexNode *oldHeadNode, FutexNode *newHeadNode) { LOS_DL_LIST *futexList = oldHeadNode->futexList.pstPrev; - LOS_ListDelete(&oldHeadNode->futexList); - LOS_ListHeadInsert(futexList, &newHeadNode->futexList); - if ((newHeadNode->queueList.pstNext == NULL) || (newHeadNode->queueList.pstPrev == NULL)) { - LOS_ListInit(&newHeadNode->queueList); + LOS_ListDelete(&oldHeadNode->futexList);//将旧节点从futexList链表上摘除 + LOS_ListHeadInsert(futexList, &newHeadNode->futexList);//将新节点从头部插入futexList链表 + if ((newHeadNode->queueList.pstNext == NULL) || (newHeadNode->queueList.pstPrev == NULL)) {//新节点前后没有等待这把锁的任务 + LOS_ListInit(&newHeadNode->queueList);//初始化等锁任务链表 } } - +/// 将参数节点从futexList上摘除 STATIC INLINE VOID OsFutexDeleteKeyFromFutexList(FutexNode *node) { LOS_ListDelete(&node->futexList); } - +/// 从哈希桶中删除快锁节点 STATIC VOID OsFutexDeleteKeyNodeFromHash(FutexNode *node, BOOL isDeleteHead, FutexNode **headNode, BOOL *queueFlags) { FutexNode *nextNode = NULL; @@ -217,8 +219,8 @@ STATIC VOID OsFutexDeleteKeyNodeFromHash(FutexNode *node, BOOL isDeleteHead, Fut return; } - if (LOS_ListEmpty(&node->queueList)) { - OsFutexDeleteKeyFromFutexList(node); + if (LOS_ListEmpty(&node->queueList)) {//如果没有任务在等锁 + OsFutexDeleteKeyFromFutexList(node);//从快锁链表上摘除 if (queueFlags != NULL) { *queueFlags = TRUE; } @@ -226,10 +228,10 @@ STATIC VOID OsFutexDeleteKeyNodeFromHash(FutexNode *node, BOOL isDeleteHead, Fut } /* FutexList is not NULL, but the header node of queueList */ - if (node->futexList.pstNext != NULL) { - if (isDeleteHead == TRUE) { - nextNode = OS_FUTEX_FROM_QUEUELIST(LOS_DL_LIST_FIRST(&node->queueList)); - OsFutexReplaceQueueListHeadNode(node, nextNode); + if (node->futexList.pstNext != NULL) {//是头节点 + if (isDeleteHead == TRUE) {//是否要删除头节点 + nextNode = OS_FUTEX_FROM_QUEUELIST(LOS_DL_LIST_FIRST(&node->queueList));//取出第一个快锁节点 + OsFutexReplaceQueueListHeadNode(node, nextNode);//两个节点交换位置 if (headNode != NULL) { *headNode = nextNode; } @@ -242,22 +244,22 @@ EXIT: OsFutexDeinitFutexNode(node); return; } - +/// 从哈希桶上删除快锁 VOID OsFutexNodeDeleteFromFutexHash(FutexNode *node, BOOL isDeleteHead, FutexNode **headNode, BOOL *queueFlags) { FutexHash *hashNode = NULL; - + //通过key找到桶号 UINT32 index = OsFutexKeyToIndex(node->key, (node->pid == OS_INVALID) ? 0 : FUTEX_PRIVATE); if (index >= FUTEX_INDEX_MAX) { return; } - hashNode = &g_futexHash[index]; + hashNode = &g_futexHash[index];//找到hash桶 if (OsMuxLockUnsafe(&hashNode->listLock, LOS_WAIT_FOREVER)) { return; } - if (node->index != index) { + if (node->index != index) {//快锁节点桶号需和哈希桶号一致 goto EXIT; } @@ -270,7 +272,6 @@ EXIT: return; } - STATIC FutexNode *OsFutexDeleteAlreadyWakeTaskAndGetNext(const FutexNode *node, FutexNode **headNode, BOOL isDeleteHead) { FutexNode *tempNode = (FutexNode *)node; @@ -292,7 +293,7 @@ STATIC FutexNode *OsFutexDeleteAlreadyWakeTaskAndGetNext(const FutexNode *node, return tempNode; } - +/// 插入一把新Futex锁到哈希桶中,只有是新的key时才会插入,因为其实存在多个FutexNode是一个key STATIC VOID OsFutexInsertNewFutexKeyToHash(FutexNode *node) { FutexNode *headNode = NULL; @@ -322,16 +323,16 @@ STATIC VOID OsFutexInsertNewFutexKeyToHash(FutexNode *node) futexList != &(hashNode->lockList); futexList = futexList->pstNext) { headNode = OS_FUTEX_FROM_FUTEXLIST(futexList); - if (node->key <= headNode->key) { + if (node->key <= headNode->key) { LOS_ListTailInsert(&(headNode->futexList), &(node->futexList)); break; } + } EXIT: return; } - STATIC INT32 OsFutexInsertFindFormBackToFront(LOS_DL_LIST *queueList, const LosTaskCB *runTask, FutexNode *node) { LOS_DL_LIST *listHead = queueList; @@ -407,55 +408,54 @@ STATIC INT32 OsFutexRecycleAndFindHeadNode(FutexNode *headNode, FutexNode *node, return LOS_OK; } - +///< 将快锁挂到任务的阻塞链表上 STATIC INT32 OsFutexInsertTasktoPendList(FutexNode **firstNode, FutexNode *node, const LosTaskCB *run) { - LosTaskCB *taskHead = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&((*firstNode)->pendList))); + LosTaskCB *taskHead = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&((*firstNode)->pendList)));//获取阻塞链表首个任务 LOS_DL_LIST *queueList = &((*firstNode)->queueList); INT32 ret1 = OsSchedParamCompare(run, taskHead); if (ret1 < 0) { /* The one with the highest priority is inserted at the top of the queue */ - LOS_ListTailInsert(queueList, &(node->queueList)); - OsFutexReplaceQueueListHeadNode(*firstNode, node); + LOS_ListTailInsert(queueList, &(node->queueList));//查到queueList的尾部 + OsFutexReplaceQueueListHeadNode(*firstNode, node);//同时交换futexList链表上的位置 *firstNode = node; return LOS_OK; } - + //如果等锁链表上没有任务或者当前任务大于链表首个任务 if (LOS_ListEmpty(queueList) && (ret1 >= 0)) { /* Insert the next position in the queue with equal priority */ - LOS_ListHeadInsert(queueList, &(node->queueList)); + LOS_ListHeadInsert(queueList, &(node->queueList));//从头部插入当前任务,当前任务是要被挂起的 return LOS_OK; } - - FutexNode *tailNode = OS_FUTEX_FROM_QUEUELIST(LOS_DL_LIST_LAST(queueList)); - LosTaskCB *taskTail = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(tailNode->pendList))); + + FutexNode *tailNode = OS_FUTEX_FROM_QUEUELIST(LOS_DL_LIST_LAST(queueList));//获取尾部节点 + LosTaskCB *taskTail = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(tailNode->pendList)));//获取阻塞任务的最后一个 INT32 ret2 = OsSchedParamCompare(taskTail, run); if ((ret2 <= 0) || (ret1 > ret2)) { - return OsFutexInsertFindFormBackToFront(queueList, run, node); + return OsFutexInsertFindFormBackToFront(queueList, run, node);//从后往前插入 } - return OsFutexInsertFindFromFrontToBack(queueList, run, node); + return OsFutexInsertFindFromFrontToBack(queueList, run, node);//否则从前往后插入 } - +/// 由指定快锁找到对应哈希桶 STATIC FutexNode *OsFindFutexNode(const FutexNode *node) { - FutexHash *hashNode = &g_futexHash[node->index]; + FutexHash *hashNode = &g_futexHash[node->index];//先找到所在哈希桶 LOS_DL_LIST *futexList = &(hashNode->lockList); FutexNode *headNode = NULL; for (futexList = futexList->pstNext; - futexList != &(hashNode->lockList); + futexList != &(hashNode->lockList);//判断循环结束条件,相等时说明跑完一轮了 futexList = futexList->pstNext) { - headNode = OS_FUTEX_FROM_FUTEXLIST(futexList); - if ((headNode->key == node->key) && (headNode->pid == node->pid)) { - return headNode; - } + headNode = OS_FUTEX_FROM_FUTEXLIST(futexList);//拿到快锁节点实体 + if ((headNode->key == node->key) && (headNode->pid == node->pid)) {//已经存在这个节点,注意这里的比较 + return headNode;//是key和pid 一起比较,因为只有这样才能确定唯一性 } return NULL; } - +///< 查找快锁并插入哈希桶中 STATIC INT32 OsFindAndInsertToHash(FutexNode *node) { FutexNode *headNode = NULL; @@ -464,7 +464,7 @@ STATIC INT32 OsFindAndInsertToHash(FutexNode *node) INT32 ret; headNode = OsFindFutexNode(node); - if (headNode == NULL) { + if (headNode == NULL) {//没有找到,说明这是一把新锁 OsFutexInsertNewFutexKeyToHash(node); LOS_ListInit(&(node->queueList)); return LOS_OK; @@ -483,14 +483,14 @@ STATIC INT32 OsFindAndInsertToHash(FutexNode *node) return ret; } - +/// 共享内存检查 STATIC INT32 OsFutexKeyShmPermCheck(const UINT32 *userVaddr, const UINT32 flags) { PADDR_T paddr; /* Check whether the futexKey is a shared lock */ - if (!(flags & FUTEX_PRIVATE)) { - paddr = (UINTPTR)LOS_PaddrQuery((UINT32 *)userVaddr); + if (!(flags & FUTEX_PRIVATE)) {//非私有快锁 + paddr = (UINTPTR)LOS_PaddrQuery((UINT32 *)userVaddr);//能否查询到物理地址 if (paddr == 0) return LOS_NOK; } @@ -549,13 +549,13 @@ STATIC INT32 OsFutexDeleteTimeoutTaskNode(FutexHash *hashNode, FutexNode *node) } return LOS_ETIMEDOUT; } - +/// 将快锁节点插入任务 STATIC INT32 OsFutexInsertTaskToHash(LosTaskCB **taskCB, FutexNode **node, const UINTPTR futexKey, const UINT32 flags) { INT32 ret; - *taskCB = OsCurrTaskGet(); - *node = &((*taskCB)->futex); - OsFutexSetKey(futexKey, flags, *node); + *taskCB = OsCurrTaskGet(); //获取当前任务 + *node = &((*taskCB)->futex); //获取当前任务的快锁节点 + OsFutexSetKey(futexKey, flags, *node);//设置参数 key index pid ret = OsFindAndInsertToHash(*node); if (ret) { @@ -565,33 +565,33 @@ STATIC INT32 OsFutexInsertTaskToHash(LosTaskCB **taskCB, FutexNode **node, const LOS_ListInit(&((*node)->pendList)); return LOS_OK; } - +/// 将当前任务挂入等待链表中 STATIC INT32 OsFutexWaitTask(const UINT32 *userVaddr, const UINT32 flags, const UINT32 val, const UINT32 timeout) { INT32 futexRet; UINT32 intSave, lockVal; LosTaskCB *taskCB = NULL; FutexNode *node = NULL; - UINTPTR futexKey = OsFutexFlagsToKey(userVaddr, flags); - UINT32 index = OsFutexKeyToIndex(futexKey, flags); + UINTPTR futexKey = OsFutexFlagsToKey(userVaddr, flags);//通过地址和flags 找到 key + UINT32 index = OsFutexKeyToIndex(futexKey, flags);//通过key找到哈希桶 FutexHash *hashNode = &g_futexHash[index]; - if (OsFutexLock(&hashNode->listLock)) { + if (OsFutexLock(&hashNode->listLock)) {//操作快锁节点链表前先上互斥锁 return LOS_EINVAL; } - - if (LOS_ArchCopyFromUser(&lockVal, userVaddr, sizeof(UINT32))) { + //userVaddr必须是用户空间虚拟地址 + if (LOS_ArchCopyFromUser(&lockVal, userVaddr, sizeof(UINT32))) {//将值拷贝到内核空间 PRINT_ERR("Futex wait param check failed! copy from user failed!\n"); futexRet = LOS_EINVAL; goto EXIT_ERR; } - if (lockVal != val) { + if (lockVal != val) {//对参数内部逻辑检查 futexRet = LOS_EBADF; goto EXIT_ERR; } - - if (OsFutexInsertTaskToHash(&taskCB, &node, futexKey, flags)) { + //注意第二个参数 FutexNode *node = NULL + if (OsFutexInsertTaskToHash(&taskCB, &node, futexKey, flags)) {// node = taskCB->futex futexRet = LOS_NOK; goto EXIT_ERR; } @@ -602,7 +602,7 @@ STATIC INT32 OsFutexWaitTask(const UINT32 *userVaddr, const UINT32 flags, const taskCB->ops->wait(taskCB, &(node->pendList), timeout); LOS_SpinUnlock(&g_taskSpin); - futexRet = OsFutexUnlock(&hashNode->listLock); + futexRet = OsFutexUnlock(&hashNode->listLock);// if (futexRet) { OsSchedUnlock(); LOS_IntRestore(intSave); @@ -632,21 +632,21 @@ EXIT_ERR: EXIT_UNLOCK_ERR: return futexRet; } - +/// 设置线程等待 | 向Futex表中插入代表被阻塞的线程的node INT32 OsFutexWait(const UINT32 *userVaddr, UINT32 flags, UINT32 val, UINT32 absTime) { INT32 ret; UINT32 timeout = LOS_WAIT_FOREVER; - ret = OsFutexWaitParamCheck(userVaddr, flags, absTime); + ret = OsFutexWaitParamCheck(userVaddr, flags, absTime);//参数检查 if (ret) { return ret; } - if (absTime != LOS_WAIT_FOREVER) { - timeout = OsNS2Tick((UINT64)absTime * OS_SYS_NS_PER_US); + if (absTime != LOS_WAIT_FOREVER) {//转换时间 , 内核的时间单位是 tick + timeout = OsNS2Tick((UINT64)absTime * OS_SYS_NS_PER_US); //转成 tick } - return OsFutexWaitTask(userVaddr, flags, val, timeout); + return OsFutexWaitTask(userVaddr, flags, val, timeout);//将任务挂起 timeOut 时长 } STATIC INT32 OsFutexWakeParamCheck(const UINT32 *userVaddr, UINT32 flags) @@ -657,12 +657,12 @@ STATIC INT32 OsFutexWakeParamCheck(const UINT32 *userVaddr, UINT32 flags) PRINT_ERR("Futex wake param check failed! error flags: 0x%x\n", flags); return LOS_EINVAL; } - + //地址必须在用户空间 if ((vaddr % sizeof(INT32)) || (vaddr < OS_FUTEX_KEY_BASE) || (vaddr >= OS_FUTEX_KEY_MAX)) { PRINT_ERR("Futex wake param check failed! error userVaddr: 0x%x\n", userVaddr); return LOS_EINVAL; } - + //必须得是个共享内存地址 if (flags && (OsFutexKeyShmPermCheck(userVaddr, flags) != LOS_OK)) { PRINT_ERR("Futex wake param check failed! error shared memory perm userVaddr: 0x%x\n", userVaddr); return LOS_EINVAL; @@ -672,7 +672,8 @@ STATIC INT32 OsFutexWakeParamCheck(const UINT32 *userVaddr, UINT32 flags) } /* Check to see if the task to be awakened has timed out - * if time out, to weak next pend task. + * if time out, to weak next pend task. + * | 查看要唤醒的任务是否超时,如果超时,就唤醒,并查看下一个挂起的任务。 */ STATIC VOID OsFutexCheckAndWakePendTask(FutexNode *headNode, const INT32 wakeNumber, FutexHash *hashNode, FutexNode **nextNode, BOOL *wakeAny) @@ -707,6 +708,7 @@ STATIC VOID OsFutexCheckAndWakePendTask(FutexNode *headNode, const INT32 wakeNum } return; } + STATIC INT32 OsFutexWakeTask(UINTPTR futexKey, UINT32 flags, INT32 wakeNumber, FutexNode **newHeadNode, BOOL *wakeAny) { @@ -715,13 +717,13 @@ STATIC INT32 OsFutexWakeTask(UINTPTR futexKey, UINT32 flags, INT32 wakeNumber, F FutexNode *headNode = NULL; UINT32 index = OsFutexKeyToIndex(futexKey, flags); FutexHash *hashNode = &g_futexHash[index]; - FutexNode tempNode = { + FutexNode tempNode = { //先组成一个临时快锁节点,目的是为了找到哈希桶中是否有这个节点 .key = futexKey, .index = index, .pid = (flags & FUTEX_PRIVATE) ? LOS_GetCurrProcessID() : OS_INVALID, }; - node = OsFindFutexNode(&tempNode); + node = OsFindFutexNode(&tempNode);//找快锁节点 if (node == NULL) { return LOS_EBADF; } @@ -729,7 +731,7 @@ STATIC INT32 OsFutexWakeTask(UINTPTR futexKey, UINT32 flags, INT32 wakeNumber, F headNode = node; SCHEDULER_LOCK(intSave); - OsFutexCheckAndWakePendTask(headNode, wakeNumber, hashNode, newHeadNode, wakeAny); + OsFutexCheckAndWakePendTask(headNode, wakeNumber, hashNode, newHeadNode, wakeAny);//再找到等这把锁的唤醒指向数量的任务 if ((*newHeadNode) != NULL) { OsFutexReplaceQueueListHeadNode(headNode, *newHeadNode); OsFutexDeinitFutexNode(headNode); @@ -741,7 +743,7 @@ STATIC INT32 OsFutexWakeTask(UINTPTR futexKey, UINT32 flags, INT32 wakeNumber, F return LOS_OK; } - +/// 唤醒一个被指定锁阻塞的线程 INT32 OsFutexWake(const UINT32 *userVaddr, UINT32 flags, INT32 wakeNumber) { INT32 ret, futexRet; @@ -750,11 +752,11 @@ INT32 OsFutexWake(const UINT32 *userVaddr, UINT32 flags, INT32 wakeNumber) FutexHash *hashNode = NULL; FutexNode *headNode = NULL; BOOL wakeAny = FALSE; - + //1.检查参数 if (OsFutexWakeParamCheck(userVaddr, flags)) { return LOS_EINVAL; } - + //2.找到指定用户空间地址对应的桶 futexKey = OsFutexFlagsToKey(userVaddr, flags); index = OsFutexKeyToIndex(futexKey, flags); @@ -762,7 +764,7 @@ INT32 OsFutexWake(const UINT32 *userVaddr, UINT32 flags, INT32 wakeNumber) if (OsFutexLock(&hashNode->listLock)) { return LOS_EINVAL; } - + //3.换起等待该锁的进程 ret = OsFutexWakeTask(futexKey, flags, wakeNumber, &headNode, &wakeAny); if (ret) { goto EXIT_ERR; @@ -776,7 +778,7 @@ INT32 OsFutexWake(const UINT32 *userVaddr, UINT32 flags, INT32 wakeNumber) if (futexRet) { goto EXIT_UNLOCK_ERR; } - + //4.根据指定参数决定是否发起调度 if (wakeAny == TRUE) { LOS_MpSchedule(OS_MP_CPU_ALL); LOS_Schedule(); @@ -885,7 +887,7 @@ STATIC VOID OsFutexRequeueSplitTwoLists(FutexHash *oldHashNode, FutexNode *oldHe tailNode->queueList.pstNext = &newHeadNode->queueList; return; } - +/// 删除旧key并获取头节点 STATIC FutexNode *OsFutexRequeueRemoveOldKeyAndGetHead(UINTPTR oldFutexKey, UINT32 flags, INT32 wakeNumber, UINTPTR newFutexKey, INT32 requeueCount, BOOL *wakeAny) { @@ -921,7 +923,7 @@ STATIC FutexNode *OsFutexRequeueRemoveOldKeyAndGetHead(UINTPTR oldFutexKey, UINT return oldHeadNode; } - +/// 检查锁在Futex表中的状态 STATIC INT32 OsFutexRequeueParamCheck(const UINT32 *oldUserVaddr, UINT32 flags, const UINT32 *newUserVaddr) { VADDR_T oldVaddr = (VADDR_T)(UINTPTR)oldUserVaddr; @@ -930,12 +932,12 @@ STATIC INT32 OsFutexRequeueParamCheck(const UINT32 *oldUserVaddr, UINT32 flags, if (oldVaddr == newVaddr) { return LOS_EINVAL; } - + //检查标记 if ((flags & (~FUTEX_PRIVATE)) != FUTEX_REQUEUE) { PRINT_ERR("Futex requeue param check failed! error flags: 0x%x\n", flags); return LOS_EINVAL; } - + //检查地址范围,必须在用户空间 if ((oldVaddr % sizeof(INT32)) || (oldVaddr < OS_FUTEX_KEY_BASE) || (oldVaddr >= OS_FUTEX_KEY_MAX)) { PRINT_ERR("Futex requeue param check failed! error old userVaddr: 0x%x\n", oldUserVaddr); return LOS_EINVAL; @@ -948,7 +950,7 @@ STATIC INT32 OsFutexRequeueParamCheck(const UINT32 *oldUserVaddr, UINT32 flags, return LOS_OK; } - +/// 调整指定锁在Futex表中的位置 INT32 OsFutexRequeue(const UINT32 *userVaddr, UINT32 flags, INT32 wakeNumber, INT32 count, const UINT32 *newUserVaddr) { INT32 ret; @@ -965,12 +967,12 @@ INT32 OsFutexRequeue(const UINT32 *userVaddr, UINT32 flags, INT32 wakeNumber, IN return LOS_EINVAL; } - oldFutexKey = OsFutexFlagsToKey(userVaddr, flags); + oldFutexKey = OsFutexFlagsToKey(userVaddr, flags);//先拿key newFutexKey = OsFutexFlagsToKey(newUserVaddr, flags); - oldIndex = OsFutexKeyToIndex(oldFutexKey, flags); + oldIndex = OsFutexKeyToIndex(oldFutexKey, flags);//再拿所在哈希桶位置,共有80个哈希桶 newIndex = OsFutexKeyToIndex(newFutexKey, flags); - oldHashNode = &g_futexHash[oldIndex]; + oldHashNode = &g_futexHash[oldIndex];//拿到对应哈希桶实体 if (OsFutexLock(&oldHashNode->listLock)) { return LOS_EINVAL; }