首页 > 其他分享 >ARM ticket spinlock 的实现

ARM ticket spinlock 的实现

时间:2023-02-23 17:44:46浏览次数:55  
标签:lock spinlock arch owner ticket spin ARM

 


https://jgsun.github.io/2021/09/12/ARM-ticket-spinlock/

ARM ticket spinlock 的实现 (jgsun.github.io)

 

ARM ticket spinlock 的实现

2021-09-12 jgsun      process  ARM  ARM64  ticket-spinlock

Overview

这是一个有点过时的题目,因为 spin_lock 已经演进到性能更好的 qsbinlock:

  • X86 enabled qspinlock support in kernel v4.2. Locking changes for v4.2,
  • Arm64 changed the default spinlock to qspinlock after the kernel 4.16rc6.

但是研究 ARM ticket spinlock 的实现可以学习 spin_lock 的进化,学习ARM atomic 操作和 ARM inline 汇编,所以记录下来方便自己以后查阅。 image

ARM V6

Arm 的 arch_spin_lock 还是使用 ticket spinlock, 源码位于:

加锁 arch_spin_lock

加锁时先将 next 保存到本地变量 lockval.tickets.next,然后将 next +1, owne保持不变。

  1. 初始化 lock.tickets.next 和lock.tickets.owner 都等于0;
  2. C0第一个加锁的立即获取锁,同时next +1, 所以这时候 lock.tickets.next =1,lock.tickets.owner = 0;
  3. C1试图获取锁,lockval.tickets.next =1,而 lockval.tickets.owner = 0;所以 wfe 进入low-power模式
  4. C0释放锁,owner++, lock.tickets.owner = 1,发 SEV 唤醒 C1
  5. C1 读取 lock.tickets.owner =1 和 lock.tickets.next 相等从而获取锁。
static inline void arch_spin_lock(arch_spinlock_t *lock)
{
    unsigned long tmp;
    u32 newval;
    arch_spinlock_t lockval;

    prefetchw(&lock->slock);    // 软件预读 &lock->slock,提前读到 cache
  // [jgsun] LL/SC(Load-Link/Store-Conditional),实现原子操作
    __asm__ __volatile__(
"1:    ldrex    %0, [%3]\n"         // 将 lock->slock 加载到 lockval, monitor 标记为 exclusive
"    add    %1, %0, %4\n"         // 将 lockval + 1, 保存到 newval
"    strex    %2, %1, [%3]\n"     // 将 newval store 到 lock->slock,如 monitor state 仍为 exclusive,
                                       // 则 store 成功,monitor state 变为 open,并置 tmp 为0,否则 store 不成功置 tmp 为非0
                                      // 如果这期间如果有其它处理器 store,monitor state 将为 open
"    teq    %2, #0\n"               // 判断tmp是否为0
"    bne    1b"                       // 如果非0,返回1继续
    : "=&r" (lockval), "=&r" (newval), "=&r" (tmp)
    : "r" (&lock->slock), "I" (1 << TICKET_SHIFT)
    : "cc"); // The "cc" clobber indicates that the assembler code modifies the flags register. 

    while (lockval.tickets.next != lockval.tickets.owner) {
        wfe(); // 如果 lockval 中的 next 不等了 owner
        lockval.tickets.owner = READ_ONCE(lock->tickets.owner);
    }

    smp_mb();
}

结构体定义 arch_spinlock_t

arch_spinlock_t 的定义在文件arch/arm/include/asm/spinlock_types.h

#define TICKET_SHIFT    16

typedef struct {
    union {
        u32 slock;
        struct __raw_tickets {
#ifdef __ARMEB__
            u16 next;
            u16 owner;
#else
            u16 owner;
            u16 next;
#endif
        } tickets;
    };
} arch_spinlock_t;

解锁 arch_spin_unlock

static inline void arch_spin_unlock(arch_spinlock_t *lock)
{
    smp_mb(); //[jgsun]dsb memory barrier
    lock->tickets.owner++; // [jgsun] owner +1 
    dsb_sev(); //[jgsun] 先调用dsb memory barrier,再调用 __asm__(SEV) 唤醒因为 WFE 指令进入 low-power 模式其他处理器
}

ARM64

ARM64 在3.13 实现了ticket lock,Arm64 changed the default spinlock to qspinlock after the kernel 4.16rc6, 4.19 Arm64 ticket lock 从内核消失了。

最新版本 ARM64 的 arch_spin_lock 已经定义为 queued_spin_lock。详见源码:

source filesource code
v5.14.2: arch/arm64/include/asm/spinlock.h #include <asm/qspinlock.h>
v5.14.2: include/asm-generic/qspinlock.h #define arch_spin_lock(l) queued_spin_lock(l)

加锁 arch_spin_lock

前面提到 4.19 以后的内核删除了ARM64 ticket lock,其最后出现内核的版本是 4.18.20:

ARMv8.1开始,ARM推出了用于原子操作的LSE(Large System Extension)指令集扩展,比LL/SC的实现方式简洁了很多,arch_spin_lock 全部使用汇编实现。

static inline void arch_spin_lock(arch_spinlock_t *lock)
{
    unsigned int tmp;
    arch_spinlock_t lockval, newval;

    asm volatile(
    /* Atomically increment the next ticket. */
    ARM64_LSE_ATOMIC_INSN(
    /* LL/SC */
"    prfm    pstl1strm, %3\n"
"1:    ldaxr    %w0, %3\n"
"    add    %w1, %w0, %w5\n"
"    stxr    %w2, %w1, %3\n"
"    cbnz    %w2, 1b\n",
    /* LSE atomics */
"    mov    %w2, %w5\n"
"    ldadda    %w2, %w0, %3\n"
    __nops(3)
    )

    /* Did we get the lock? */
"    eor    %w1, %w0, %w0, ror #16\n"
"    cbz    %w1, 3f\n"
    /*
     * No: spin on the owner. Send a local event to avoid missing an
     * unlock before the exclusive load.
     */
"    sevl\n"
"2:    wfe\n"
"    ldaxrh    %w2, %4\n"
"    eor    %w1, %w2, %w0, lsr #16\n"
"    cbnz    %w1, 2b\n"
    /* We got the lock. Critical section starts here. */
"3:"
    : "=&r" (lockval), "=&r" (newval), "=&r" (tmp), "+Q" (*lock)
    : "Q" (lock->owner), "I" (1 << TICKET_SHIFT) //Q: A memory address which uses a single base register with no offset
    : "memory");
}

结构体定义 arch_spinlock_t

#define TICKET_SHIFT    16

typedef struct {
#ifdef __AARCH64EB__
    u16 next;
    u16 owner;
#else
    u16 owner;
    u16 next;
#endif
} __aligned(4) arch_spinlock_t;

解锁 arch_spin_unlock

static inline void arch_spin_unlock(arch_spinlock_t *lock)
{
    unsigned long tmp;

    asm volatile(ARM64_LSE_ATOMIC_INSN(
    /* LL/SC */
    "    ldrh    %w1, %0\n"
    "    add    %w1, %w1, #1\n"
    "    stlrh    %w1, %0",
    /* LSE atomics */
    "    mov    %w1, #1\n"
    "    staddlh    %w1, %0\n"
    __nops(1))
    : "=Q" (lock->owner), "=&r" (tmp)
    :
    : "memory");
}

参考资料

标签:lock,spinlock,arch,owner,ticket,spin,ARM
From: https://www.cnblogs.com/sinferwu/p/17148898.html

相关文章

  • arrch架构部署redis,报错: ignore-warnings ARM64-COW-BUG
    做个记录。 arrch架构的redis安装包下载链接:https://pan.baidu.com/s/1TMXNpMvMDWRFD1f5km7MwQ  提取码:36qk 启动redis报错如下:Rediswillnowexittoprev......
  • ARM应用调试思路、方法总结、笔记
    一、应用调试1:使用strace命令来跟踪系统调用二、应用调试2:使用GDB来调试应用程序编译gdb,gdbservertarxjfgdb-7.4.tar.bz2cdgdb-7.4/./configure--target=arm-linuxm......
  • 自学python-安装python/pycharm-day03
    安装解释器/学习工具pycharm1.Python简介诞生python的创始人为吉多·范罗苏姆(GuidovanRossum),一般称龟叔。1989年的圣诞节期间,龟叔为了在阿姆斯特丹打发时间,决心......
  • OpenHarmony 分布式相机(中)
    作者:徐金生接上一篇OpenHarmony分布式相机(上),今天我们来说下如何实现分布式相机。实现分布式相机其实很简单,正如官方介绍的一样,当被控端相机被连接成功后,可以像使用本地设......
  • 如果个人pc上要装不同社区版本的pycharm,安装时需要注意的一点
    pycharm下载地址[包含了目前发行的所有版本]:https://www.jetbrains.com/pycharm/download/other.html选择指定的版本,点击     勾选uninstallsilently(sett......
  • HarmonyOS Connect认证测试
     在HarmonyOSConnect生态产品的认证测试过程中,你是否存在这些疑问:认证流程具体包括哪些操作环节?如何根据实际场景选择合适的认证方式?如何选择认证测试标准的版本……......
  • [ABC111D] Robot Arms
    \(\mathcalLink\)先判断无解情况。显然,每一步无论怎么走都会使奇偶性发生相同的改变,因此当\(\existsi,j\)使得\(x_i+y_i\not\equivx_j+y_j\pmod2\)时无解。考虑......
  • Pycharm_windows中,Pycharm用(os.environ['HOMEPATH']拼接路径的配置文件,读取不到配置
    问题描述:pycharm用(os.environ['HOMEPATH']拼接路径的配置文件,读取不到配置文件内容,为空[]同样的路径,用cmd就能读取到配置文件内容1、cmd执行效果:>>>config=configp......
  • python和pycharm的安装与使用
    Python如何下载与安装?最新版本不具备最好的兼容性与稳定性 系统解释器建议一个版本的就行 建议安装3.7-3.10之间的版本 安装时注意你的操作系统的位数64位操作系......
  • 行业大咖云集 多元观点碰撞 OpenHarmony技术峰会与你相约深圳
    2023年2月25日,第一届开放原子开源基金会OpenHarmony技术峰会(以下简称技术峰会)将于深圳隆重召开。本次技术峰会由OpenAtomOpenHarmony(以下简称OpenHarmony)技术指导委员会主......