1 Star 5 Fork 7

laokz / OS kernel test

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
futex.md 3.93 KB
一键复制 编辑 原始数据 按行查看 历史
laokz 提交于 2021-01-06 19:39 . update futex '1

探讨futex的几个问题

清理已醒节点问题

阻塞等待futex锁的线程在超时后,会有短暂的不一致状态,即:超时后内核定时器将其加入就绪队列准备调度,而其futex节点仍在锁的等待队列中;当线程重新运行后,才将节点摘出。这期间为不一致状态时间。为了适应这种情形,futex实现中有多处清理已醒节点的代码。由于这种不一致状态的不确定性,逻辑比较复杂易出问题。下面以WAIT操作为例简要分析几个关键环节。

  1. OsFutexWaitTask获取互斥锁保护以下操作过程。

  2. OsFutexRecycleAndFindHeadNode获取一次任务锁,调用OsFutexDeleteAlreadyWakeTaskAndGetNext,删除已醒节点,遇到首个仍在等待的节点即停止,并返回这个firstNode节点。

  3. OsFindAndInsertToHash再获取一次任务锁,调用OsFutexInsertTasktoPendList,将线程futex节点按优先级降序插入到firstNode领头的队列。

在2、3环节之间,futex操作未持有任务锁,因此定时器可能操作,前述不一致状态可能出现,也就是说,OsFutexInsertTasktoPendList再操作的firstNode、tailNode都可能是已醒节点,其.pendList指向自身,得到的TCB将是错误数据: LosTaskCB *taskHead = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&((*firstNode)->pendList)));

接着调用的OsFutexInsertFindFormBackToFront、OsFutexInsertFindFromFrontToBack也要删除已醒节点,甚至清空整个队列,那么计算线程TCB、优先级比较、for循环的正确性都可能出问题:

tempNode = OsFutexDeleteAlreadyWakeTaskAndGetNext(tempNode, NULL, FALSE);
taskTail = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&(tempNode->pendList)));

阻塞队列优先级问题

阻塞等待futex锁的线程,按优先级降序加入锁的等待队列。但可能因为线程优先级的动态性,而使得队列的优先级是乱序。

futex的互斥锁属性采用的是默认值,即优先级继承协议,这样线程在持有互斥锁时,可能会因为别人(包括别的进程)也想获取这个互斥锁,而改变优先级,从而插入到错误的位置。

REQUEUE新旧互斥锁获取问题

当REQUEUE操作的旧锁和新锁不是一个时,采取的是用一个获取一个的方法。这个时间差可能带来隐患。比如,已释放旧锁尚未获取新锁时,要转移的队列没有任何保护,其线程可能因超时被唤醒,并调用OsFutexDeleteTimeoutTaskNode删除自己;即使已经获取了新锁,因超时线程持有的是旧锁,两者可能同时操作同一个节点。

解决这个问题最简单的办法是同时获取这两把锁,但这对于线程因超时需要安全删除自己来说仍是困难的:比如key1时阻塞,期间被REQUEUE为key2,再次REQUEUE为key3时超时醒来,线程只知道锁1,需要读键值确定删除是否安全;REQUEUE线程同时锁定锁2、锁3,需要修改键值;两者将不可避免地进行实际无锁保护的竞争。

建议调整数据结构,消除不一致状态

目前的FutexNode数据结构,表示的基本都是锁的固有属性,只有.pendList表示的是阻塞场所,唯一地对应一个具体线程。.queueList完全可以替代.pendList的功能。

建议把现在绑定到TCB的futexNode独立出来,作为一个动态分配的数据结构表示一把用户锁,需要时创建并连接到futex哈希表。线程WAIT、WAKE时,均针对该结构进行操作,象通常的阻塞、唤醒一样,直接用TCB的.pendList成员连接、摘出阻塞链表(.queueList)。动态分配的用户锁可以在进程退出时销毁。

这样区分后,上述问题一和问题三的第二部分就不存在了,futex操作简化很多(节点清理删除、队列头替换等均不需要了)。

以上仅是静态分析,说的很多也是边际情况,并且目前futex功能支持也有限,但就设计而言,仍期望指正与探讨。

C
1
https://gitee.com/laokz/OS-kernel-test.git
git@gitee.com:laokz/OS-kernel-test.git
laokz
OS-kernel-test
OS kernel test
master

搜索帮助