linux spin_lock
设计思想
设置三条路径,快,中,慢;
获取锁
- 快速:快速路径简单判断一个值;获取锁时标记其被locked;
- 中速:其被locked时,进入中速,中速就是等待这个locked为0;中速的时候为了标记中速已被占领,还需要通过一个pending标记;
- 慢速:检查lock有值,证明我应该进入中速;又发现pending被置为我就应该进入慢速;慢速就通过mcs 链表实现;
- 慢速中,要等待pending空闲(中),要等待locked空闲;
- 如果慢速存在prev节点,要先等待自身被唤醒,然后再等待locked空闲;
释放锁:
- 中速获取就是等待locked 空闲,获取锁时也要把pending 清0,表示中速空闲;设置locked
- 慢速要等到lockd 和 pending都空闲;获取锁时如果有next,记得还要唤醒next;
实际代码中上面的两个操作方式放在加锁的过程中;
释放锁的代码只设置了locked空闲,只用设置locked空闲,整个就会像流水线一样,一个一个处理;
比如msc node,第一个node获取了锁,之前第二个自旋的就会唤醒,一个一个的接着一个;
代码实现:
前言
整个过程非常绕,作者考虑各种特殊情况,以及优化处理,所以顺序阅读代码不是特别好理解;
- 整理一个具体的场景:CPU0,CPU1,CPU2 3个CPU顺序去获取锁;
- val状态模型;
快速路径
场景:只有CPU0去获取锁:
- 判断val是否为0,此时val状态为(0,0,0,0),将val值设置为_Q_LOCKED_VAL(1<<0),获取锁并返回;
- val状态为:(0,0,0,1);
中速路径
场景:CPU0去获取锁并且还没释放期间,CPU1去获取锁;
-
判断val是否为0,val状态为(0,0,0,1),进入慢速路径;
-
判断
_Q_PENDING_VAL
(0,0,1,0),判断~_Q_LOCKED_MASK
(*, *, x, x),此时val 状态为(0,0,0,1),明显不满足,所以根本不进入; -
set_pending_acquire 或上_Q_PENDING_VAL,此时val状态为(0,0,1,1);
-
又再次判断
~_Q_LOCKED_MASK
,不进入; -
进入
if(val & _Q_LOCKD_MASK)
分支,原子等待_Q_LOCKED_MASK为0;(等待点) -
往下走证明前级释放锁了,此时状态为(0,0,1,0);这是一个中间状态,cpu0正在释放锁,cpu1没获取锁,但是即将获取锁;所以开头进行了_Q_PENDING_VAL的判断;
-
clear pending 并且set locked;也就是状态为(0,0,0,1);
慢速路径 - 1
场景:CPU0占有锁,CPU1又去获取锁,CPU2又去排队获取锁;
- 此时val状态为(0, 0, 1, 1);
- 进入queue流程,主要是mcs node思想;
- 更新lock的tail域
- 等待lock pending,locked 为 0;(等待点)
- 如果没有next节点,直接设置locked的值为1 就返回;
- 如果有next节点,只设置lock域为1,然后更新next 的 locked 域为 1;进行next的唤醒
慢速路径 - 2
场景:CPU0占有锁,CPU1又去获取锁,CPU2又去排队获取锁,cpu3 又去排队获取锁;
- 会通过old判断tail域不为0,所以加入链表mcs 链表中;
- 然后等待自身locked 域为 1;(等待点)
特殊处理
再355 进行了 pending + tail 的判断,为什么372又进行了再次判断??
很可能进来的时候只设置了lock filed,但是由于发生了中断,再次返回时,tail 以及pending 又可能有了新值了;此时应该进入queue处理;(如果没有这个判断就行了pending处理)
所以通过372进行了一个再次判断,先判断旧值的tail + pending是否为0,不为0都应该进入queue;如果val的旧值没有设置pending,证明还错写了pending(走到这里一定会设置pending),所以还应该clear_pending;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话