http://weharmonyos.com/openharmony/zh-cn/device-dev/kernel/kernel-small-basic-trans-user-mutex.html https://www.jianshu.com/p/d17a6152740c 更多...
结构体 | |
struct | FutexHash |
单独哈希桶,上面挂了一个个 FutexNode 更多... | |
函数 | |
STATIC INT32 | OsFutexLock (LosMux *lock) |
对互斥锁封装 更多... | |
STATIC INT32 | OsFutexUnlock (LosMux *lock) |
初始化Futex(Fast userspace mutex,用户态快速互斥锁)模块 更多... | |
UINT32 | OsFutexInit (VOID) |
LOS_MODULE_INIT (OsFutexInit, LOS_INIT_LEVEL_KMOD_EXTENDED) | |
注册Futex模块 更多... | |
STATIC VOID | OsFutexShowTaskNodeAttr (const LOS_DL_LIST *futexList) |
VOID | OsFutexHashShow (VOID) |
STATIC INLINE UINTPTR | OsFutexFlagsToKey (const UINT32 *userVaddr, const UINT32 flags) |
通过用户空间地址获取哈希key 更多... | |
STATIC INLINE UINT32 | OsFutexKeyToIndex (const UINTPTR futexKey, const UINT32 flags) |
通过哈希key获取索引 更多... | |
STATIC INLINE VOID | OsFutexSetKey (UINTPTR futexKey, UINT32 flags, FutexNode *node) |
设置快锁哈希key 更多... | |
STATIC INLINE VOID | OsFutexDeinitFutexNode (FutexNode *node) |
STATIC INLINE VOID | OsFutexReplaceQueueListHeadNode (FutexNode *oldHeadNode, FutexNode *newHeadNode) |
新旧两个节点交换 futexList 位置 更多... | |
STATIC INLINE VOID | OsFutexDeleteKeyFromFutexList (FutexNode *node) |
将参数节点从futexList上摘除 更多... | |
STATIC VOID | OsFutexDeleteKeyNodeFromHash (FutexNode *node, BOOL isDeleteHead, FutexNode **headNode, BOOL *queueFlags) |
从哈希桶中删除快锁节点 更多... | |
VOID | OsFutexNodeDeleteFromFutexHash (FutexNode *node, BOOL isDeleteHead, FutexNode **headNode, BOOL *queueFlags) |
从哈希桶上删除快锁 更多... | |
STATIC FutexNode * | OsFutexDeleteAlreadyWakeTaskAndGetNext (const FutexNode *node, FutexNode **headNode, BOOL isDeleteHead) |
这块代码谁写的? 这种命名 ... 更多... | |
STATIC VOID | OsFutexInsertNewFutexKeyToHash (FutexNode *node) |
插入一把新Futex锁到哈希桶中,只有是新的key时才会插入,因为其实存在多个FutexNode是一个key 更多... | |
STATIC INT32 | OsFutexInsertFindFormBackToFront (LOS_DL_LIST *queueList, const LosTaskCB *runTask, FutexNode *node) |
STATIC INT32 | OsFutexInsertFindFromFrontToBack (LOS_DL_LIST *queueList, const LosTaskCB *runTask, FutexNode *node) |
STATIC INT32 | OsFutexRecycleAndFindHeadNode (FutexNode *headNode, FutexNode *node, FutexNode **firstNode) |
将快锁挂到任务的阻塞链表上 更多... | |
STATIC INT32 | OsFutexInsertTasktoPendList (FutexNode **firstNode, FutexNode *node, const LosTaskCB *run) |
STATIC FutexNode * | OsFindFutexNode (const FutexNode *node) |
由指定快锁找到对应哈希桶 更多... | |
STATIC INT32 | OsFindAndInsertToHash (FutexNode *node) |
STATIC INT32 | OsFutexKeyShmPermCheck (const UINT32 *userVaddr, const UINT32 flags) |
共享内存检查 更多... | |
STATIC INT32 | OsFutexWaitParamCheck (const UINT32 *userVaddr, UINT32 flags, UINT32 absTime) |
STATIC INT32 | OsFutexDeleteTimeoutTaskNode (FutexHash *hashNode, FutexNode *node) |
STATIC INT32 | OsFutexInsertTaskToHash (LosTaskCB **taskCB, FutexNode **node, const UINTPTR futexKey, const UINT32 flags) |
将快锁节点插入任务 更多... | |
STATIC INT32 | OsFutexWaitTask (const UINT32 *userVaddr, const UINT32 flags, const UINT32 val, const UINT32 timeout) |
将当前任务挂入等待链表中 更多... | |
INT32 | OsFutexWait (const UINT32 *userVaddr, UINT32 flags, UINT32 val, UINT32 absTime) |
设置线程等待 | 向Futex表中插入代表被阻塞的线程的node 更多... | |
STATIC INT32 | OsFutexWakeParamCheck (const UINT32 *userVaddr, UINT32 flags) |
STATIC VOID | OsFutexCheckAndWakePendTask (FutexNode *headNode, const INT32 wakeNumber, FutexHash *hashNode, FutexNode **nextNode, BOOL *wakeAny) |
STATIC INT32 | OsFutexWakeTask (UINTPTR futexKey, UINT32 flags, INT32 wakeNumber, FutexNode **newHeadNode, BOOL *wakeAny) |
OsFutexWakeTask 唤醒任务 更多... | |
INT32 | OsFutexWake (const UINT32 *userVaddr, UINT32 flags, INT32 wakeNumber) |
唤醒一个被指定锁阻塞的线程 更多... | |
STATIC INT32 | OsFutexRequeueInsertNewKey (UINTPTR newFutexKey, INT32 newIndex, FutexNode *oldHeadNode) |
STATIC VOID | OsFutexRequeueSplitTwoLists (FutexHash *oldHashNode, FutexNode *oldHeadNode, UINT32 flags, UINTPTR futexKey, INT32 count) |
STATIC FutexNode * | OsFutexRequeueRemoveOldKeyAndGetHead (UINTPTR oldFutexKey, UINT32 flags, INT32 wakeNumber, UINTPTR newFutexKey, INT32 requeueCount, BOOL *wakeAny) |
删除旧key并获取头节点 更多... | |
STATIC INT32 | OsFutexRequeueParamCheck (const UINT32 *oldUserVaddr, UINT32 flags, const UINT32 *newUserVaddr) |
检查锁在Futex表中的状态 更多... | |
INT32 | OsFutexRequeue (const UINT32 *userVaddr, UINT32 flags, INT32 wakeNumber, INT32 count, const UINT32 *newUserVaddr) |
调整指定锁在Futex表中的位置 更多... | |
变量 | |
FutexHash | g_futexHash [FUTEX_INDEX_MAX] |
80个哈希桶 更多... | |
http://weharmonyos.com/openharmony/zh-cn/device-dev/kernel/kernel-small-basic-trans-user-mutex.html https://www.jianshu.com/p/d17a6152740c
Futex 由一块能够被多个进程共享的内存空间(一个对齐后的整型变量)组成;这个整型变量的值能够通过汇编语言调用CPU提供的原子操作指令来增加或减少, 并且一个进程可以等待直到那个值变成正数。Futex 的操作几乎全部在用户空间完成;只有当操作结果不一致从而需要仲裁时,才需要进入操作系统内核空间执行。 这种机制允许使用 futex 的锁定原语有非常高的执行效率:由于绝大多数的操作并不需要在多个进程之间进行仲裁,所以绝大多数操作都可以在应用程序空间执行, 而不需要使用(相对高代价的)内核系统调用。 基本概念 Futex(Fast userspace mutex,用户态快速互斥锁)是内核提供的一种系统调用能力,通常作为基础组件与用户态的相关 锁逻辑结合组成用户态锁,是一种用户态与内核态共同作用的锁,例如用户态mutex锁、barrier与cond同步锁、读写锁。 其用户态部分负责锁逻辑,内核态部分负责锁调度。 当用户态线程请求锁时,先在用户态进行锁状态的判断维护,若此时不产生锁的竞争,则直接在用户态进行上锁返回; 反之,则需要进行线程的挂起操作,通过Futex系统调用请求内核介入来挂起线程,并维护阻塞队列。 当用户态线程释放锁时,先在用户态进行锁状态的判断维护,若此时没有其他线程被该锁阻塞,则直接在用户态进行解锁返回; 反之,则需要进行阻塞线程的唤醒操作,通过Futex系统调用请求内核介入来唤醒阻塞队列中的线程。 历史 futex (fast userspace mutex) 是Linux的一个基础组件,可以用来构建各种更高级别的同步机制,比如锁或者信号量等等, POSIX信号量就是基于futex构建的。大多数时候编写应用程序并不需要直接使用futex,一般用基于它所实现的系统库就够了。 传统的SystemV IPC(inter process communication)进程间同步机制都是通过内核对象来实现的,以 semaphore 为例, 当进程间要同步的时候,必须通过系统调用semop(2)进入内核进行PV操作。系统调用的缺点是开销很大,需要从user mode 切换到kernel mode、保存寄存器状态、从user stack切换到kernel stack、等等,通常要消耗上百条指令。事实上, 有一部分系统调用是可以避免的,因为现实中很多同步操作进行的时候根本不存在竞争,即某个进程从持有semaphore直至 释放semaphore的这段时间内,常常没有其它进程对同一semaphore有需求,在这种情况下,内核的参与本来是不必要的, 可是在传统机制下,持有semaphore必须先调用semop(2)进入内核去看看有没有人和它竞争,释放semaphore也必须调用semop(2) 进入内核去看看有没有人在等待同一semaphore,这些不必要的系统调用造成了大量的性能损耗。 设计思想 futex的解决思路是:在无竞争的情况下操作完全在user space进行,不需要系统调用,仅在发生竞争的时候进入内核去完成 相应的处理(wait 或者 wake up)。所以说,futex是一种user mode和kernel mode混合的同步机制,需要两种模式合作才能完成, futex变量必须位于user space,而不是内核对象,futex的代码也分为user mode和kernel mode两部分,无竞争的情况下在user mode, 发生竞争时则通过sys_futex系统调用进入kernel mode进行处理 运行机制 当用户态产生锁的竞争或释放需要进行相关线程的调度操作时,会触发Futex系统调用进入内核,此时会将用户态锁的地址 传入内核,并在内核的Futex中以锁地址来区分用户态的每一把锁,因为用户态可用虚拟地址空间为1GiB,为了便于查找、 管理,内核Futex采用哈希桶来存放用户态传入的锁。 当前哈希桶共有80个,0~63号桶用于存放私有锁(以虚拟地址进行哈希),64~79号桶用于存放共享锁(以物理地址进行哈希), 私有/共享属性通过用户态锁的初始化以及Futex系统调用入参确定。 如下图: 每个futex哈希桶中存放被futex_list串联起来的哈希值相同的futex node,每个futex node对应一个被挂起的task, node中key值唯一标识一把用户态锁,具有相同key值的node被queue_list串联起来表示被同一把锁阻塞的task队列。
在文件 los_futex.c 中定义.
LOS_MODULE_INIT | ( | OsFutexInit | , |
LOS_INIT_LEVEL_KMOD_EXTENDED | |||
) |
注册Futex模块
在文件 los_futex.c 第 516 行定义.
STATIC VOID OsFutexCheckAndWakePendTask | ( | FutexNode * | headNode, |
const INT32 | wakeNumber, | ||
FutexHash * | hashNode, | ||
FutexNode ** | nextNode, | ||
BOOL * | wakeAny | ||
) |
在文件 los_futex.c 第 735 行定义.
STATIC INLINE VOID OsFutexDeinitFutexNode | ( | FutexNode * | node | ) |
在文件 los_futex.c 第 246 行定义.
STATIC FutexNode * OsFutexDeleteAlreadyWakeTaskAndGetNext | ( | const FutexNode * | node, |
FutexNode ** | headNode, | ||
BOOL | isDeleteHead | ||
) |
这块代码谁写的? 这种命名 ...
在文件 los_futex.c 第 330 行定义.
STATIC INLINE VOID OsFutexDeleteKeyFromFutexList | ( | FutexNode * | node | ) |
STATIC VOID OsFutexDeleteKeyNodeFromHash | ( | FutexNode * | node, |
BOOL | isDeleteHead, | ||
FutexNode ** | headNode, | ||
BOOL * | queueFlags | ||
) |
从哈希桶中删除快锁节点
在文件 los_futex.c 第 268 行定义.
在文件 los_futex.c 第 587 行定义.
VOID OsFutexHashShow | ( | VOID | ) |
在文件 los_futex.c 第 190 行定义.
UINT32 OsFutexInit | ( | VOID | ) |
在文件 los_futex.c 第 144 行定义.
STATIC INT32 OsFutexInsertFindFormBackToFront | ( | LOS_DL_LIST * | queueList, |
const LosTaskCB * | runTask, | ||
FutexNode * | node | ||
) |
在文件 los_futex.c 第 392 行定义.
STATIC INT32 OsFutexInsertFindFromFrontToBack | ( | LOS_DL_LIST * | queueList, |
const LosTaskCB * | runTask, | ||
FutexNode * | node | ||
) |
STATIC VOID OsFutexInsertNewFutexKeyToHash | ( | FutexNode * | node | ) |
插入一把新Futex锁到哈希桶中,只有是新的key时才会插入,因为其实存在多个FutexNode是一个key
从后往前插入快锁 Form写错了 @note_thinking
在文件 los_futex.c 第 352 行定义.
STATIC INT32 OsFutexInsertTaskToHash | ( | LosTaskCB ** | taskCB, |
FutexNode ** | node, | ||
const UINTPTR | futexKey, | ||
const UINT32 | flags | ||
) |
将快锁节点插入任务
在文件 los_futex.c 第 610 行定义.
STATIC INT32 OsFutexInsertTasktoPendList | ( | FutexNode ** | firstNode, |
FutexNode * | node, | ||
const LosTaskCB * | run | ||
) |
在文件 los_futex.c 第 468 行定义.
通过哈希key获取索引
在文件 los_futex.c 第 225 行定义.
对互斥锁封装
在文件 los_futex.c 第 124 行定义.
VOID OsFutexNodeDeleteFromFutexHash | ( | FutexNode * | node, |
BOOL | isDeleteHead, | ||
FutexNode ** | headNode, | ||
BOOL * | queueFlags | ||
) |
从哈希桶上删除快锁
在文件 los_futex.c 第 302 行定义.
STATIC INLINE VOID OsFutexReplaceQueueListHeadNode | ( | FutexNode * | oldHeadNode, |
FutexNode * | newHeadNode | ||
) |
INT32 OsFutexRequeue | ( | const UINT32 * | userVaddr, |
UINT32 | flags, | ||
INT32 | wakeNumber, | ||
INT32 | count, | ||
const UINT32 * | newUserVaddr | ||
) |
调整指定锁在Futex表中的位置
在文件 los_futex.c 第 1022 行定义.
STATIC INT32 OsFutexRequeueInsertNewKey | ( | UINTPTR | newFutexKey, |
INT32 | newIndex, | ||
FutexNode * | oldHeadNode | ||
) |
在文件 los_futex.c 第 866 行定义.
STATIC INT32 OsFutexRequeueParamCheck | ( | const UINT32 * | oldUserVaddr, |
UINT32 | flags, | ||
const UINT32 * | newUserVaddr | ||
) |
检查锁在Futex表中的状态
在文件 los_futex.c 第 995 行定义.
STATIC FutexNode * OsFutexRequeueRemoveOldKeyAndGetHead | ( | UINTPTR | oldFutexKey, |
UINT32 | flags, | ||
INT32 | wakeNumber, | ||
UINTPTR | newFutexKey, | ||
INT32 | requeueCount, | ||
BOOL * | wakeAny | ||
) |
删除旧key并获取头节点
在文件 los_futex.c 第 959 行定义.
STATIC VOID OsFutexRequeueSplitTwoLists | ( | FutexHash * | oldHashNode, |
FutexNode * | oldHeadNode, | ||
UINT32 | flags, | ||
UINTPTR | futexKey, | ||
INT32 | count | ||
) |
设置快锁哈希key
在文件 los_futex.c 第 239 行定义.
STATIC VOID OsFutexShowTaskNodeAttr | ( | const LOS_DL_LIST * | futexList | ) |
设置线程等待 | 向Futex表中插入代表被阻塞的线程的node
在文件 los_futex.c 第 693 行定义.
在文件 los_futex.c 第 557 行定义.
STATIC INT32 OsFutexWaitTask | ( | const UINT32 * | userVaddr, |
const UINT32 | flags, | ||
const UINT32 | val, | ||
const UINT32 | timeout | ||
) |
将当前任务挂入等待链表中
在文件 los_futex.c 第 626 行定义.
唤醒一个被指定锁阻塞的线程
在文件 los_futex.c 第 815 行定义.
在文件 los_futex.c 第 709 行定义.
STATIC INT32 OsFutexWakeTask | ( | UINTPTR | futexKey, |
UINT32 | flags, | ||
INT32 | wakeNumber, | ||
FutexNode ** | newHeadNode, | ||
BOOL * | wakeAny | ||
) |
OsFutexWakeTask 唤醒任务
flags | |
futexKey | |
newHeadNode | |
wakeAny | |
wakeNumber | 唤醒数量 |
在文件 los_futex.c 第 781 行定义.
FutexHash g_futexHash[FUTEX_INDEX_MAX] |
80个哈希桶
在文件 los_futex.c 第 121 行定义.