土法炼钢兴趣小组的算法知识备份

【操作系统百科】spinlock 家族

文章导航

分类入口
os
标签入口
#spinlock#ticket-lock#mcs#qspinlock#numa

目录

spinlock 是内核最基本的同步原语——持有时不能睡眠、不能被抢占。从最简单的 test-and-set 到如今的 qspinlock,四代演进都在解决一个问题:公平性和 NUMA 扩展性

一、先看图

flowchart LR
    TAS[test-and-set<br/>不公平] --> TICKET[ticket lock<br/>FIFO 公平]
    TICKET --> MCS[MCS lock<br/>本地自旋]
    MCS --> QSPIN[qspinlock<br/>混合方案<br/>4 字节]
    QSPIN --> PVQSPIN[paravirt qspinlock<br/>虚拟化优化]

    classDef gen fill:#388bfd22,stroke:#388bfd,color:#adbac7;
    class TAS,TICKET,MCS,QSPIN,PVQSPIN gen

二、原始 spinlock(test-and-set)

while (test_and_set(&lock))
    cpu_relax();  // 自旋

问题:

三、ticket lock

struct ticket_lock {
    atomic_t next;   // 取号
    atomic_t owner;  // 当前持有者
};

每个线程取号 → 等自己号码 = owner → 公平(FIFO)。

问题:所有核自旋在同一 cacheline(owner)→ 释放锁时 invalidate 风暴。

四、MCS lock

struct mcs_node {
    struct mcs_node *next;
    int locked;  // 本地自旋变量
};

每个核在自己的 mcs_node.locked 上自旋(本地 cacheline)→ 释放锁时只唤醒下一个。

优势:O(1) cache invalidation → NUMA 友好。 问题:需要额外内存(每核一个 node)→ 不能直接替换 4 字节 spinlock。

五、qspinlock

Linux 4.2+ 的默认 spinlock。4 字节内编码三层状态:

union {
    atomic_t val;
    struct {
        u8 locked;    // 是否已锁
        u8 pending;   // 是否有人等待(fast path)
        u16 tail;     // MCS 队列尾
    };
};

5.1 三路径

  1. Fast path:lock 为 0 → CAS 获取(一条原子指令)
  2. Pending path:lock 被持有但无队列 → 设 pending 位 → 自旋等 locked 清零
  3. Slow path:已有 pending → 入 MCS 队列 → 本地自旋

5.2 优势

六、paravirt qspinlock

虚拟化场景:持锁 vCPU 被 hypervisor 调度走 → 其他 vCPU 白白自旋(lock holder preemption)。

PV qspinlock(4.8+):检测到持锁者未运行 → halt 当前 vCPU → hypervisor 优先调度持锁者。

七、spin_lock 变体

API 禁止 场景
spin_lock() 抢占 进程上下文,无中断竞争
spin_lock_bh() 抢占 + 软中断 与 softirq 共享数据
spin_lock_irq() 抢占 + 硬中断 与硬中断共享数据
spin_lock_irqsave() 同上 + 保存 flags 不知道当前中断状态

错误使用 → 死锁或中断延迟。

八、rwlock 的退休

rwlock_t:多读者并行、写者独占。

问题:读者侧仍是全局计数器 → cache line bouncing → 多核性能差。

替代:RCU(读侧零开销)、percpu_rwsem。

九、PREEMPT_RT 下的 spinlock

PREEMPT_RT 把 spinlock_t 替换为 rt_mutex → 可睡眠 → 优先级继承。

只有 raw_spinlock_t 保持真正的自旋(硬中断路径等)。

十、小结


参考文献

工具


上一篇原子 RMW 下一篇mutex/rwsem

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-04-30 · os

【操作系统百科】NUMA 内存

多路服务器里内存不再平等——本地访问和远程访问延迟差 2-3 倍。本文讲 NUMA 拓扑、mempolicy、AutoNUMA、NUMA balancing、CXL 带来的分级内存层次,以及 NUMA 感知的生产调优。

2026-04-27 · os

【操作系统百科】内存回收

Linux 内存回收是 VM 最复杂的子系统之一。本文讲 active/inactive LRU、kswapd 与 direct reclaim、watermark 三线、swappiness 的真实含义、MGLRU 改造、memcg 回收与 PSI。

2026-04-28 · os

【操作系统百科】交换

swap 还值得开吗?本文讲 swap area 基础、swap cache、zram 压缩内存、zswap 前端压缩池、swappiness 的真实含义、容器里的 swap 策略,以及为什么现代 Android 全靠 zram 不靠磁盘。

2026-05-03 · os

【操作系统百科】Slab/SLUB 分配器

buddy 只管页粒度(4K+),内核大多数对象只有几十到几百字节。slab/SLUB 在 buddy 之上做对象级缓存。本文讲 slab 历史、SLUB 接手、SLOB 退场、kmem_cache、per-CPU cache、KASAN 集成。


By .