zoukankan      html  css  js  c++  java
  • 自旋锁原理分析

    1. 概念

    自旋锁的目的是在短期间内进行轻量级的锁定,解决对某项共享资源的互斥使用,在等待锁重新可用期间进行自旋,所以自旋锁不应该被持有时间过长,如果需要长时间锁定的话,推荐使用信号量。实际操作的数据结构如下:

    2. 获取锁

    最终执行的代码是体系结构相关的自旋锁实现:arch_spin_lock。

    3. 代码分析

    static inline void arch_spin_lock(arch_spinlock_t *lock)
    {
      unsigned long tmp;
      u32 newval;
      arch_spinlock_t lockval;
      // 处理器通知内存系统将对某个地址的内存进行读写
      prefetchw(&lock->slock);
      // 以独占的方式对 lock->tickets.next 执行 +1 操作
      __asm__ __volatile__(
    "1:  ldrex  %0, [%3]
    "
    "  add  %1, %0, %4
    "
    "  strex  %2, %1, [%3]
    "
    "  teq  %2, #0
    "
    "  bne  1b"
      : "=&r" (lockval), "=&r" (newval), "=&r" (tmp)
      : "r" (&lock->slock), "I" (1 << TICKET_SHIFT)
      : "cc");
      // 判断是否轮到自己拥有自旋锁
      while (lockval.tickets.next != lockval.tickets.owner) {
        // 将当前核心挂起等待其他核心发送信号,也就是等 SEV 指令
        wfe();
        // 读取自旋锁中的 lock->tickets.owner
        lockval.tickets.owner = ACCESS_ONCE(lock->tickets.owner);
      }
      // 数据同步
      smp_mb();
    }
    

    4. 释放锁

    最终执行的代码是体系结构相关的自旋锁实现:arch_spin_unlock。

    5. 代码分析

    static inline void arch_spin_unlock(arch_spinlock_t *lock)
    {
      // 数据同步
      smp_mb();
      // 将自旋锁交给下一个使用者
      lock->tickets.owner++;
      // 先进行数据同步,然后给其他核心发信号
      dsb_sev();
    }
    

    6. 总结

    自旋锁底层实现依赖于体系结构相关的汇编指令,在进行自旋锁操作时,使用独占指令LDREX/STREX;在自旋时使用指令WFE将当前核心挂起,等待被唤醒;当核心在释放自旋锁时,使用SEV指令通知其他所有核心。

  • 相关阅读:
    LeetCode
    LeetCode
    Django ORM 查询
    The Usage of Pymongo
    MongoDB基操
    Django内置auth模块中login_required装饰器用于类视图的优雅方式
    Django Session配置
    Python虚拟环境
    遇见Flask-Script
    Git使用手册
  • 原文地址:https://www.cnblogs.com/jiau/p/13182019.html
Copyright © 2011-2022 走看看