Skip to content

Linux Locking 子系统深度分析 R2

目录

  1. spinlock 实现分析
  2. mutex 实现分析
  3. rwsem 实现分析
  4. percpu 机制分析
  5. lockdep 依赖验证机制
  6. 知识点关联表

1. spinlock 实现分析

1.1 数据结构布局

raw_spinlock_t 结构体 (include/linux/spinlock_types_raw.h:14-24)

c
context_lock_struct(raw_spinlock) {
    arch_spinlock_t raw_lock;        // 架构相关的自旋锁
#ifdef CONFIG_DEBUG_SPINLOCK
    unsigned int magic, owner_cpu;   // 调试信息
    void *owner;
#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOC
    struct lockdep_map dep_map;      // lockdep 依赖图节点
#endif
};

RAW_LOCK_INIT 初始化宏 (include/linux/spinlock_types_raw.h:63-67)

c
#define __RAW_SPIN_LOCK_INITIALIZER(lockname)   \
{                                               \
    .raw_lock = __ARCH_SPIN_LOCK_UNLOCKED,      \
    SPIN_DEBUG_INIT(lockname)                   \
    RAW_SPIN_DEP_MAP_INIT(lockname) }

1.2 spin_lock/unlock 实现

核心实现 (kernel/locking/spinlock.c:136-213)

spinlock 的实现采用宏展开方式,核心实现在 spinlock_api_smp.h 中:

c
// spinlock.c:152-155 - spin_lock 入口
static inline void __raw_spin_lock(raw_spinlock_t *lock)
    __acquires(lock) __no_context_analysis
{
    preempt_disable();
    spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
    LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);
}

// spinlock.c:164-170 - spin_unlock 实现
static inline void __raw_spin_unlock(raw_spinlock_t *lock)
    __releases(lock)
{
    spin_release(&lock->dep_map, _RET_IP_);
    do_raw_spin_unlock(lock);
    preempt_enable();
}

trylock 实现 (kernel/locking/spinlock.c:136-140):

c
static inline int __raw_spin_trylock(raw_spinlock_t *lock)
    __cond_acquires(true, lock)
{
    preempt_disable();
    if (do_raw_spin_trylock(lock)) {
        spin_acquire(&lock->dep_map, 0, 1, _RET_IP_);
        return 1;
    }
    preempt_enable();
    return 0;
}

1.3 x86 qspinlock (队列自旋锁)

x86 架构使用 qspinlock 替代传统的 ticket spinlock,通过 MCS 队列避免高速缓存行弹跳。

qspinlock 结构 (include/asm-generic/qspinlock_types.h:14-44):

c
typedef struct qspinlock {
    union {
        atomic_t val;
#ifdef __LITTLE_ENDIAN
        struct {
            u8  locked;      // 锁定字节
            u8  pending;     // 待处理位
        };
        struct {
            u16 locked_pending;
            u16 tail;        // 队尾 CPU ID
        };
#endif
    };
} arch_spinlock_t;

位域定义 (include/asm-generic/qspinlock_types.h:67-93):

  • Bit 0-7: locked byte (锁持有标志)
  • Bit 8: pending (等待标志)
  • Bit 9-10: tail index (队尾索引,在 NR_CPUS >= 16K 时使用)
  • Bit 11-31: tail cpu (队尾 CPU 编号 + 1)

加锁流程 (include/asm-generic/qspinlock.h:107-115):

c
static __always_inline void queued_spin_lock(struct qspinlock *lock)
{
    int val = 0;
    if (likely(atomic_try_cmpxchg_acquire(&lock->val, &val, _Q_LOCKED_VAL)))
        return;
    queued_spin_lock_slowpath(lock, val);  // 进入慢路径
}

解锁流程 (include/asm-generic/qspinlock.h:123-129):

c
static __always_inline void queued_spin_unlock(struct qspinlock *lock)
{
    smp_store_release(&lock->locked, 0);  // 释放语义
}

1.4 Ticket Spinlock vs MCS 队列对比

特性Ticket SpinlockMCS Queue Spinlock (qspinlock)
实现复杂度简单复杂
缓存行弹跳所有等待者轮询同一缓存行仅相邻节点交互
公平性FIFO 严格FIFO 严格
扩展性差 (2^16 CPU 上限)好 (无实质限制)
内存开销O(1)O(n) 但每个节点仅 3 个字

Linux 现代版本默认使用 qspinlock,但通过 arch/x86/include/asm/spinlock.h:26 条件引入。

1.5 内存屏障

spinlock 实现依赖架构特定的内存序:

  • 加锁: atomic_try_cmpxchg_acquire() - acquire 语义确保临界区访问前的操作不会重排到临界区内
  • 解锁: smp_store_release() - release 语义确保临界区内的操作不会重排到临界区外

2. mutex 实现分析

2.1 数据结构布局

struct mutex (kernel/locking/mutex.c:21 + 隐式定义):

c
struct mutex {
    atomic_long_t owner;           // 持有者 + 标志位
    raw_spinlock_t wait_lock;      // 保护等待队列
    struct list_head wait_list;     // 等待者链表 (FIFO)
#ifdef CONFIG_MUTEX_SPIN_ON_OWNER
    struct optimistic_spin_queue osq;  // MCS 队列用于乐观自旋
#endif
#ifdef CONFIG_DEBUG_MUTEXES
    void *magic;
#endif
};

owner 字段编码 (kernel/locking/mutex.c:57-71):

c
// 最低 3 位为标志位
#define MUTEX_FLAG_WAITERS    0x01  // 有等待者
#define MUTEX_FLAG_HANDOFF    0x02  // 移交标志
#define MUTEX_FLAG_PICKUP     0x04  // 拾取标志

static inline struct task_struct *__owner_task(unsigned long owner)
{
    return (struct task_struct *)(owner & ~MUTEX_FLAGS);
}

2.2 fast/slow path 设计

快速路径 (无竞争) (kernel/locking/mutex.c:152-163):

c
static __always_inline bool __mutex_trylock_fast(struct mutex *lock)
{
    unsigned long curr = (unsigned long)current;
    unsigned long zero = 0UL;

    if (atomic_long_try_cmpxchg_acquire(&lock->owner, &zero, curr))
        return true;  // 成功获取锁
    return false;
}

慢速路径入口 (kernel/locking/mutex.c:262-291):

c
void __sched mutex_lock(struct mutex *lock)
{
    might_sleep();
    if (!__mutex_trylock_fast(lock))    // 先尝试快速路径
        __mutex_lock_slowpath(lock);    // 失败则进入慢路径
}

慢速路径核心 (kernel/locking/mutex.c:577-770):

c
static __always_inline int __sched
__mutex_lock_common(struct mutex *lock, unsigned int state, ...)
{
    // ... 
    preempt_disable();
    mutex_acquire_nest(&lock->dep_map, ...);
    
    // 尝试乐观自旋
    if (__mutex_trylock(lock) ||
        mutex_optimistic_spin(lock, ww_ctx, NULL)) {
        lock_acquired(&lock->dep_map, ip);
        preempt_enable();
        return 0;
    }
    
    // 获取等待锁并加入等待队列
    raw_spin_lock_irqsave(&lock->wait_lock, flags);
    __mutex_add_waiter(lock, &waiter, &lock->wait_list);
    
    // 睡眠等待
    for (;;) {
        if (__mutex_trylock(lock))
            goto acquired;
        if (signal_pending_state(state, current)) {
            ret = -EINTR;
            goto err;
        }
        raw_spin_unlock_irqrestore_wake(&lock->wait_lock, flags, &wake_q);
        schedule_preempt_disabled();
        raw_spin_lock_irqsave(&lock->wait_lock, flags);
    }
}

2.3 mutex_trylock 实现

trylock 核心 (kernel/locking/mutex.c:84-118):

c
static inline struct task_struct *__mutex_trylock_common(struct mutex *lock, bool handoff)
{
    unsigned long owner, curr = (unsigned long)current;
    owner = atomic_long_read(&lock->owner);
    
    for (;;) {  // 循环处理竞态
        unsigned long flags = __owner_flags(owner);
        unsigned long task = owner & ~MUTEX_FLAGS;
        
        if (task) {
            if (flags & MUTEX_FLAG_PICKUP) {
                if (task != curr)
                    break;  // 被其他任务持有
                flags &= ~MUTEX_FLAG_PICKUP;
            } else if (handoff) {
                if (flags & MUTEX_FLAG_HANDOFF)
                    break;
                flags |= MUTEX_FLAG_HANDOFF;
            } else {
                break;  // 锁已被持有
            }
        } else {
            // 锁空闲,尝试获取
            task = curr;
        }
        
        // CAS 操作获取锁
        if (atomic_long_try_cmpxchg_acquire(&lock->owner, &owner, task | flags)) {
            if (task == curr)
                return NULL;  // 成功
            break;
        }
    }
    return __owner_task(owner);  // 返回当前持有者
}

2.4 osq_lock (乐观自旋队列)

osq_node 结构 (kernel/locking/osq_lock.c:15-19):

c
struct optimistic_spin_node {
    struct optimistic_spin_node *next, *prev;
    int locked;   // 1 = 锁已被持有
    int cpu;      // 编码的 CPU 编号 + 1
};
DEFINE_PER_CPU_SHARED_ALIGNED(struct optimistic_spin_node, osq_node);

osq_lock 实现 (kernel/locking/osq_lock.c:93-208):

c
bool osq_lock(struct optimistic_spin_queue *lock)
{
    struct optimistic_spin_node *node = this_cpu_ptr(&osq_node);
    struct optimistic_spin_node *prev, *next;
    int curr = encode_cpu(smp_processor_id());
    
    node->locked = 0;
    node->next = NULL;
    node->cpu = curr;
    
    // 原子操作入队
    old = atomic_xchg(&lock->tail, curr);
    if (old == OSQ_UNLOCKED_VAL)
        return true;  // 锁空闲,直接获取
    
    prev = decode_cpu(old);
    node->prev = prev;
    
    smp_wmb();  // 内存屏障确保 prev->next 顺序
    
    WRITE_ONCE(prev->next, node);  // 加入 MCS 队列
    
    // 等待锁或被取消
    if (smp_cond_load_relaxed(&node->locked, VAL || need_resched() || ...))
        return true;
    
    // 出队逻辑...
}

osq_unlock 实现 (kernel/locking/osq_lock.c:210-234):

c
void osq_unlock(struct optimistic_spin_queue *lock)
{
    struct optimistic_spin_node *node, *next;
    int curr = encode_cpu(smp_processor_id());
    
    // 快速路径:无竞争时直接解锁
    if (atomic_try_cmpxchg_release(&lock->tail, &curr, OSQ_UNLOCKED_VAL))
        return;
    
    // 通知下一个等待者
    node = this_cpu_ptr(&osq_node);
    next = xchg(&node->next, NULL);
    if (next) {
        WRITE_ONCE(next->locked, 1);  // 唤醒
        return;
    }
    next = osq_wait_next(lock, node, OSQ_UNLOCKED_VAL);
    if (next)
        WRITE_ONCE(next->locked, 1);
}

活锁避免机制: osq_lock 确保同一时刻只有一个 spinner 尝试自旋等待,通过 MCS 队列严格序列化竞争者,防止多 spinner 同时自旋导致的性能退化。


3. rwsem 读写信号量实现分析

3.1 数据结构布局

struct rw_semaphore (kernel/locking/rwsem.c:33 + 隐式定义):

c
struct rw_semaphore {
    atomic_long_t count;           // 计数器
    raw_spinlock_t wait_lock;     // 保护等待队列
    struct list_head wait_list;    // 等待者链表
#ifdef CONFIG_RWSEM_SPIN_ON_OWNER
    struct optimistic_spin_queue osq;  // 乐观自旋队列
#endif
    atomic_long_t owner;           // 持有者 (调试用)
#ifdef CONFIG_DEBUG_RWSEMS
    void *magic;
#endif
};

3.2 count 位域设计

位域定义 (kernel/locking/rwsem.c:118-129):

c
#define RWSEM_WRITER_LOCKED     (1UL << 0)    // 写者锁定位
#define RWSEM_FLAG_WAITERS      (1UL << 1)    // 等待者存在位
#define RWSEM_FLAG_HANDOFF      (1UL << 2)    // 移交位
#define RWSEM_FLAG_READFAIL     (1UL << (BITS_PER_LONG - 1))  // 读者失败位

#define RWSEM_READER_SHIFT      8              // 读者计数偏移
#define RWSEM_READER_BIAS       (1UL << RWSEM_READER_SHIFT)

64位架构 count 位布局:

  • Bit 0: writer locked bit
  • Bit 1: waiters present bit
  • Bit 2: lock handoff bit
  • Bit 3-7: reserved
  • Bit 8-62: 55-bit reader count
  • Bit 63: read fail bit

3.3 read_lock/write_lock 语义

读锁获取 (kernel/locking/rwsem.c:249-262):

c
static inline bool rwsem_read_trylock(struct rw_semaphore *sem, long *cntp)
{
    *cntp = atomic_long_add_return_acquire(RWSEM_READER_BIAS, &sem->count);
    
    if (WARN_ON_ONCE(*cntp < 0))
        rwsem_set_nonspinnable(sem);
    
    if (!(*cntp & RWSEM_READ_FAILED_MASK)) {
        rwsem_set_reader_owned(sem);
        return true;
    }
    return false;
}

写锁获取 (kernel/locking/rwsem.c:264-274):

c
static inline bool rwsem_write_trylock(struct rw_semaphore *sem)
{
    long tmp = RWSEM_UNLOCKED_VALUE;
    
    if (atomic_long_try_cmpxchg_acquire(&sem->count, &tmp, RWSEM_WRITER_LOCKED)) {
        rwsem_set_owner(sem);
        return true;
    }
    return false;
}

3.4 Writer 乐观自旋

写锁慢路径 (kernel/locking/rwsem.c:1110-1208):

c
static struct rw_semaphore __sched *
rwsem_down_write_slowpath(struct rw_semaphore *sem, int state)
{
    // 首先尝试乐观自旋
    if (rwsem_can_spin_on_owner(sem) && rwsem_optimistic_spin(sem))
        return sem;  // 自旋获取成功
    
    // 加入等待队列
    waiter.task = current;
    waiter.type = RWSEM_WAITING_FOR_WRITE;
    
    raw_spin_lock_irq(&sem->wait_lock);
    rwsem_add_waiter(sem, &waiter);
    
    // 设置 HANDOFF 标志以便锁持有者直接移交
    if (waiter.handoff_set) {
        // 自旋等待 owner 变为 NULL
        if (rwsem_spin_on_owner(sem) == OWNER_NULL)
            goto trylock_again;
    }
    
    schedule_preempt_disabled();
}

乐观自旋条件检查 (kernel/locking/rwsem.c:704-729):

c
static inline bool rwsem_can_spin_on_owner(struct rw_semaphore *sem)
{
    struct task_struct *owner;
    unsigned long flags;
    
    if (need_resched())
        return false;
    
    owner = rwsem_owner_flags(sem, &flags);
    
    // 不可自旋条件:
    // 1. 锁被标记为非自旋
    // 2. 持有者是读者
    // 3. 持有者不在运行
    if ((flags & RWSEM_NONSPINNABLE) ||
        (owner && !(flags & RWSEM_READER_OWNED) && !owner_on_cpu(owner)))
        return false;
    
    return true;
}

3.5 读者批唤醒

rwsem_mark_wake (kernel/locking/rwsem.c:410-567) 实现读者批唤醒,一次最多唤醒 MAX_READERS_WAKEUP (0x100) 个读者。


4. percpu 机制分析

4.1 DEFINE_PER_CPU 实现

宏定义 (include/linux/percpu-defs.h:110-114):

c
#define DECLARE_PER_CPU(type, name) \
    DECLARE_PER_CPU_SECTION(type, name, "")

#define DEFINE_PER_CPU(type, name) \
    DEFINE_PER_CPU_SECTION(type, name, "")

节段属性 (include/linux/percpu-defs.h:47-49):

c
#define __PCPU_ATTRS(sec) \
    __percpu __attribute__((section(PER_CPU_BASE_SECTION sec))) \
    PER_CPU_ATTRIBUTES

每个 CPU 有一个独立的 percpu 副本,位于不同的内存区域。

4.2 percpu_read/write 实现

per_cpu_ptr (include/linux/percpu-defs.h:237-241):

c
#define per_cpu_ptr(ptr, cpu) \
({  __verify_pcpu_ptr(ptr); \
    SHIFT_PERCPU_PTR((ptr), per_cpu_offset((cpu))); \
})

this_cpu_read (include/linux/percpu-defs.h:499):

c
#define this_cpu_read(pcp) __pcpu_size_call_return(this_cpu_read_, pcp)

编译时根据变量大小展开为 this_cpu_read_1/2/4/8,直接操作当前 CPU 的 percpu 副本。

4.3 percpu_counter 结构

percpu_counter (include/linux/percpu_counter.h:22-29):

c
struct percpu_counter {
    raw_spinlock_t lock;      // 保护全局计数
    s64 count;                // 全局计数 (近似值)
#ifdef CONFIG_HOTPLUG_CPU
    struct list_head list;    // 热插拔 CPU 链表
#endif
    s32 __percpu *counters;   // 每 CPU 本地计数数组
};

批量同步机制: percpu_counter 使用批量更新减少锁竞争:

  • 本地更新先存入 counters[cpu]
  • 调用 percpu_counter_sum() 时才累加所有本地计数到全局 count

4.4 percpu 内存屏障和同步

percpu 操作天然提供内存序保证:

  • raw_cpu_read() / raw_cpu_write(): 无额外屏障,依赖 CPU 内存序
  • __this_cpu_read() / __this_cpu_write(): 调试模式下检查 preempt 状态
  • this_cpu_read() / this_cpu_write(): 无保护,适用于原子上下文中

跨 CPU 同步: 涉及跨 CPU 访问时需要显式内存屏障:

c
// percpu 操作在跨 CPU 场景下的顺序性由以下保证
smp_mb();  // 确保所有 CPU 看到一致的内存视图

5. lockdep 依赖验证机制

5.1 依赖图构建

核心数据结构 (kernel/locking/lockdep.c:207-225):

c
// 锁类节点
struct lock_class {
    struct lockdep_subclass_key *key;
    struct list_head locks_after;     // 依赖此锁的锁列表
    struct list_head locks_before;    // 此锁依赖的锁列表
    // ...
};

// 依赖边
struct lock_list {
    struct list_head entry;
    struct lock_class *class;
    struct lock_class *links_to;      // 指向目标锁类
    u8 dep;                           // 依赖类型 (ER/SR/EN/SN)
    u16 distance;                     // 距离
    struct lock_trace *trace;         // 获取时的栈回溯
    // ...
};

全局变量 (kernel/locking/lockdep.c:207-224):

c
unsigned long nr_list_entries;
static struct lock_list list_entries[MAX_LOCKDEP_ENTRIES];
struct lock_class lock_classes[MAX_LOCKDEP_KEYS];

// 哈希表加速查找
#define CLASSHASH_SIZE (1UL << CLASSHASH_BITS)
static struct hlist_head classhash_table[CLASSHASH_SIZE];

注册锁类 (kernel/locking/lockdep.c:1284-1394):

c
static struct lock_class *register_lock_class(struct lockdep_map *lock, 
                                              unsigned int subclass, int force)
{
    // 1. 查找或分配 lock_class
    class = look_up_lock_class(lock, subclass);
    if (likely(class)) goto out_set_class_cache;
    
    // 2. 分配新类
    class = list_first_entry_or_null(&free_lock_classes, ...);
    // ...
    
    // 3. 加入全局链表和哈希表
    hlist_add_head_rcu(&class->hash_entry, hash_head);
    list_move_tail(&class->lock_entry, &all_lock_classes);
}

5.2 环检测算法 (BFS)

循环队列 (kernel/locking/lockdep.c:1469-1526):

c
struct circular_queue {
    struct lock_list *element[MAX_CIRCULAR_QUEUE_SIZE];
    unsigned int front, rear;
};

static struct circular_queue lock_cq;

static inline int __cq_enqueue(struct circular_queue *cq, struct lock_list *elem)
{
    if (__cq_full(cq)) return -1;
    cq->element[cq->rear] = elem;
    cq->rear = (cq->rear + 1) & CQ_MASK;
    return 0;
}

BFS 搜索 (kernel/locking/lockdep.c:1733-1839):

c
static enum bfs_result __bfs(struct lock_list *source_entry, ...)
{
    struct circular_queue *cq = &lock_cq;
    struct lock_list *lock = NULL;
    
    __cq_init(cq);
    __cq_enqueue(cq, source_entry);
    
    while ((lock = __bfs_next(lock, offset)) || (lock = __cq_dequeue(cq))) {
        if (lock_accessed(lock)) continue;  // 已访问
        mark_lock_accessed(lock);
        
        // 强依赖路径检查 -(*R)-> -(S*)-> 不是强依赖
        if (lock->parent) {
            u8 dep = lock->dep;
            bool prev_only_xr = lock->parent->only_xr;
            
            if (prev_only_xr)
                dep &= ~(DEP_SR_MASK | DEP_SN_MASK);
            if (!dep) continue;
            
            lock->only_xr = !(dep & (DEP_SN_MASK | DEP_EN_MASK));
        }
        
        if (match(lock, data))    // 找到目标
            return BFS_RMATCH;
        
        // 扩展搜索图
        list_for_each_entry_rcu(entry, &lock->class->locks_after, entry) {
            visit_lock_entry(entry, lock);
            if (__cq_enqueue(cq, entry)) return BFS_EQUEUEFULL;
        }
    }
    return BFS_RNOMATCH;
}

5.3 锁顺序验证

check_prev_add (kernel/locking/lockdep.c:3121-3199) 在每次加锁时执行验证:

c
static int check_prev_add(struct task_struct *curr, 
                         struct held_lock *prev,
                         struct held_lock *next, ...)
{
    // 1. 检查循环依赖
    ret = check_noncircular(next, prev, trace);
    if (unlikely(bfs_error(ret) || ret == BFS_RMATCH))
        return 0;  // 检测到循环
    
    // 2. 检查 IRQ 安全性
    if (!check_irq_usage(curr, prev, next))
        return 0;
    
    // 3. 添加依赖边
    list_for_each_entry(entry, &hlock_class(prev)->locks_after, entry) {
        if (entry->class == hlock_class(next)) {
            entry->dep |= calc_dep(prev, next);  // 更新依赖类型
            return 1;
        }
    }
    // 添加新依赖边...
}

5.4 强依赖路径

依赖类型 (kernel/locking/lockdep.c:1620-1639):

c
#define DEP_SR_BIT 0  // 共享读 -> 递归读
#define DEP_ER_BIT 1   // 互斥 -> 递归读  
#define DEP_SN_BIT 2   // 共享读 -> 非递归
#define DEP_EN_BIT 3   // 互斥 -> 非递归

// 强依赖: 不包含 -(*R)-> -(S*)-> 模式

hlock_conflict (kernel/locking/lockdep.c:1996-2003):

c
static inline bool hlock_conflict(struct lock_list *entry, void *data)
{
    struct held_lock *hlock = (struct held_lock *)data;
    
    return hlock_class(hlock) == entry->class &&
           (hlock->read == 0 || !entry->only_xr);
    // B -> A 是 -(E*)-> 或 A -> .. -> B 是 -(*N)->
}

6. 知识点关联表

组件核心结构关键算法同步原语典型应用
spinlockraw_spinlock_t / qspinlockMCS 队列atomic_cmpxchg_acquire中断上下文、短期保护
mutexstruct mutexosq_lock 乐观自旋atomic_long_try_cmpxchg进程上下文、长期等待
rwsemstruct rw_semaphorewriter optimistic spinningatomic_long_add_return读多写少场景
percpuDEFINE_PER_CPU节段变量per_cpu_ptr / this_cpu_*每 CPU 数据
percpu_counterstruct percpu_counter批量同步raw_spinlock近似计数
lockdeplock_class + lock_listBFS 环检测图遍历 + 循环队列死锁检测

关键源码位置索引

文件行号描述
kernel/locking/spinlock.c136-213spinlock trylock/lock/unlock 实现
kernel/locking/mutex.c84-118__mutex_trylock_common
kernel/locking/mutex.c152-170__mutex_trylock_fast / __mutex_unlock_fast
kernel/locking/mutex.c444-518mutex_optimistic_spin
kernel/locking/osq_lock.c93-208osq_lock MCS 入队
kernel/locking/osq_lock.c210-234osq_unlock
kernel/locking/rwsem.c118-129rwsem count 位域定义
kernel/locking/rwsem.c249-274rwsem_read_trylock / rwsem_write_trylock
kernel/locking/rwsem.c816-932rwsem_optimistic_spin
include/asm-generic/qspinlock.h51-130qspinlock 加解锁
include/asm-generic/qspinlock_types.h14-44qspinlock 结构体
include/linux/percpu-defs.h237-257per_cpu_ptr / this_cpu_ptr
include/linux/percpu_counter.h22-29percpu_counter 结构体
kernel/locking/lockdep.c207-224lockdep 核心数据结构
kernel/locking/lockdep.c1733-1839BFS 搜索 __bfs
kernel/locking/lockdep.c3121-3199check_prev_add 验证
kernel/locking/lockdep.c1469-1526循环队列实现

文档版本: R2生成日期: 2026-04-26分析范围: kernel/locking/spinlock.c, mutex.c, rwsem.c, mm/percpu.c, kernel/locking/lockdep.c

基于 VitePress 构建