• 同步 -- 互斥锁


     本篇文章基于Linux-6.5源码

    建议:搭配Linux源码观看更佳

    1. struct mutex {
    2. atomic_long_t owner;
    3. spinlock_t wait_lock; //自旋锁,该自旋锁的作用是保护后面的等待队列的原子性
    4. struct list_head wait_list; //等待队列
    5. };

    API接口

    mutex_init

    互斥锁初始化比较简单,就是把owner,wait_lock,wait_list这几个成员初始化一下

    1. #define mutex_init(mutex) \
    2. do { \
    3. static struct lock_class_key __key; \
    4. \
    5. __mutex_init((mutex), #mutex, &__key); \
    6. } while (0)
    7. void __mutex_init(struct mutex *lock, const char *name, struct lock_class_key *key)
    8. {
    9. atomic_long_set(&lock->owner, 0);//初始化锁的所有者
    10. spin_lock_init(&lock->wait_lock);//初始化自旋锁
    11. INIT_LIST_HEAD(&lock->wait_list);//初始化等待队列
    12. }

    mutex_lock

    加锁:mutex_lock

    1. void __sched mutex_lock(struct mutex *lock)
    2. {
    3. might_sleep();
    4. //尝试直接加锁,如果不成功,则进入slowpath,
    5. if (!__mutex_trylock_fast(lock))
    6. __mutex_lock_slowpath(lock);
    7. }
    8. EXPORT_SYMBOL(mutex_lock);
    9. static __always_inline bool __mutex_trylock_fast(struct mutex *lock)
    10. {
    11. unsigned long curr = (unsigned long)current;//sp_el0,指向当前进程的task_struct
    12. unsigned long zero = 0UL;
    13. //判断owner是否为0,如果为0表示当前锁没有被占用,则把current写入owner返回true表示加锁成功
    14. if (atomic_long_try_cmpxchg_acquire(&lock->owner, &zero, curr))
    15. return true;
    16. //owner不为0,表示锁被占用了,返回false
    17. return false;
    18. }

    __mutex_lock_slowpath(慢加锁)中执行的过程大概是:

    mutex_unlock

    解锁:mutex_unlock

    1. void __sched mutex_unlock(struct mutex *lock)
    2. {
    3. #ifndef CONFIG_DEBUG_LOCK_ALLOC
    4. if (__mutex_unlock_fast(lock))
    5. return;
    6. #endif
    7. __mutex_unlock_slowpath(lock, _RET_IP_);
    8. }
    9. EXPORT_SYMBOL(mutex_unlock);

    __mutex_unlock_fast(快解锁):比较lock->owner和curr是否一致,一致则直接把0写到lock->owner中,表示解锁。

    __mutex_unlock_slowpath:等待队列的第一个对象出列,表示下一个将要获得锁的任务。把下一个任务的task_struct地址写入到mutex lock的owner变量中(相当于下一个任务获得了互斥锁),唤醒下一个任务继续执行。

  • 相关阅读:
    数据库概论(简单介绍)
    什么GAN生成对抗网络?生成对抗网络可以干什么?
    微服务保护(熔断)和阿里Sentinel
    经验笔记 - 01_Vue+SpringBoot实现文件上传(单文件上传、单页面多处地方需要上传)
    STM32单片机蓝牙APP手势语音温控电风扇落地扇人体感应
    Verilog基础:阻塞/非阻塞赋值
    没想到我这浓眉大眼的,也有被人催更的一天~
    java 从resource下载excel打不开
    leetcode:环形链表
    CMake变量可见性学习
  • 原文地址:https://blog.csdn.net/qq_52353238/article/details/133014737