linux内核:mutex锁

发布时间 2023-10-12 00:26:59作者: 小海哥哥de

简单来说,
mutex 结构体要最少包含着两部分 {
atomic:标识状态
mutex_queue: 存在等待任务
}

struct mutex {
    /*
     * 1. 标记mutex对象被哪一个task(struct task_struct*)持有,如果为NULL表示还没有
     * 被任何一个任务持有。
     * 2. 由于task_struct至少是8字节对齐的,其最低3bit可以用来做标志位,分别为:
     * (1) MUTEX_FLAG_WAITERS:表示 wait_list 成员链表非空,即有任务阻塞在此mutex锁上,
     * owner在unlock的时候必须要执行唤醒动作。
     * (2) MUTEX_FLAG_HANDOFF:为了防止mutex等待队列中的任务饿死,在唤醒top waiter时会
     * 设置这个标志(由于乐观自旋任务的不断插入,唤醒的top waiter任务也不一定能获取到锁),
     * 设置这个标志后,owner在解锁时会将锁直接转交给top waiter,而不是让唤醒的top waiter
     * 去竞争锁。
     * (3) MUTEX_FLAG_PICKUP:此标志表示mutex已经完事具备(即完成了转交),只等待top waiter
     * 来持锁。
     */
    atomic_long_t    owner;
    //用于保护 wait_list 成员链表的自旋锁
    spinlock_t        wait_lock;
#ifdef CONFIG_MUTEX_SPIN_ON_OWNER //默认使能
    /*
     * 在配置了 MUTEX_SPIN_ON_OWNER 的时候,mutex支持乐观自旋机制,osq成员就是乐观自旋时需
     * 要持有的MCS锁队列,其只有一个tail成员,如果等于0说明是个空队列,没有乐观自旋任务。否
     * 则tail指向队列的尾部。注意tail不是指针是个cpu number,optimistic_spin_node对象是per-cpu
     * 的,有cpu number就能定位到 optimistic_spin_node 对象。
     */
    struct optimistic_spin_queue osq; /* Spinner MCS lock */
#endif
    /*
     * mutex是个睡眠锁,当任务无法获取到锁又不具备乐观自旋条件时会挂入到这个等待队列,等待owner
     * 释放锁。
     */
    struct list_head    wait_list;
#ifdef CONFIG_DEBUG_MUTEXES //默认关闭
    //debug相关成员
    void            *magic;
#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOC //默认关闭
    //debug相关成员
    struct lockdep_map    dep_map;
#endif
    ANDROID_OEM_DATA_ARRAY(1, 2);
};

资料:
https://zhuanlan.zhihu.com/p/624064959