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;

posted @   _xingxing  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示