DragonflyBSD:锁定管理器(kern_lock.c)代码中可能的竞争条件?

问题描述 投票:0回答:1

最近我一直在阅读lock_manager(kern_lock.c)代码,并遇到了一些我认为会产生竞争条件的情况。

步骤1:

@@ undo_shreq(...):如果有待处理的升级请求,则代码将重置“ LKC_UPREQ”标志并进行wakeup()调用;仅当

时才发生
(count & (LKC_EXREQ | LKC_UPREQ | LKC_CANCEL)) &&

       (count & (LKC_SMASK | LKC_XMASK)) == 0)

步骤2:

现在,并行地,另一个线程T2试图获取互斥锁,并且达到了琐碎的条件(即@lockmgr_exclusive(...)] >>

if ((count & (LKC_UPREQ | LKC_EXREQ |
      LKC_XMASK)) == 0 &&
    ((count & LKC_SHARED) == 0 ||
     (count & LKC_SMASK) == 0))

因此,T2将计数增加1并将其自身设置为所有者线程-这意味着它获得了排他性。

步骤3:

线程(T1)睡在步骤1唤醒的LKC_UPREQ标志上;这是睡眠后的代码(....之后,LK_SLEEPFAIL和睡眠错误的健全性检查),@ lockmgr_upgrade(...)

if ((count & LKC_UPREQ) == 0) {           // reset by step 1
KKASSERT((count & LKC_XMASK) == 1);      // true, by step 2
lkp->lk_lockholder = td;
break;
}

[我看到(如果错了,请纠正我),在步骤3中,线程T1将lk_lockholder重置为其自身-意味着,它具有排他性!

最近,我一直在阅读lock_manager(kern_lock.c)代码,并遇到了一些我认为会产生竞争条件的情况。步骤1:@undo_shreq(...):如果有升级请求...

bsd dragonfly-bsd
1个回答
1
投票

其工作方式是,如果一个线程设置UPREQ然后进入睡眠状态,则另一个线程将授予它排他锁并将其唤醒。授予线程清除UPREQ并增加独占计数,但是不知道“谁”设置了UPREQ,因此由设置UPREQ来设置锁持有者字段的线程决定。

由于lockmgr代码必须同时处理许多独占的饥饿,许多独占的饥饿以及死锁边缘情况,所以它相当复杂。在过去的一两年中发现了一些边缘案例,但是对我来说,这个特殊案例似乎并不像个bug。有点令人困惑,因为第二个线程授予了排他锁(UPREQ已清除,并且excl计数递增),但是第一个线程仍负责设置lk_lockholder字段。

© www.soinside.com 2019 - 2024. All rights reserved.