【问题标题】:How is a spin lock woken up in Linux/ARM64?如何在 Linux/ARM64 中唤醒自旋锁?
【发布时间】:2015-11-23 10:13:24
【问题描述】:

在Linux内核中,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. */
"   prfm    pstl1strm, %3\n"
"1: ldaxr   %w0, %3\n"
"   add %w1, %w0, %w5\n"
"   stxr    %w2, %w1, %3\n"
"   cbnz    %w2, 1b\n"
    /* 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)
    : "memory");
}

请注意,“wfe”指令将处理器置于低功耗模式并等待设置事件寄存器。 ARMv8 手册规定,如果清除了 PE 的全局监视器,则会生成一个事件(第 D1.17.1 节)。这应该由解锁部分完成。但是让我们看看 arch_spin_unlock() 部分:

static inline void arch_spin_unlock(arch_spinlock_t *lock)
{
    asm volatile(
"   stlrh   %w1, %0\n"
    : "=Q" (lock->owner)
    : "r" (lock->owner + 1)
    : "memory");
}

没有SEV!!那么,这里是什么唤醒锁WFE呢?

PS:我一直在寻找任何 ARM64 汇编教程,但没有找到。如果有人有任何建议,那就太棒了。谢谢!

【问题讨论】:

    标签: assembly linux-kernel arm64


    【解决方案1】:

    锁定时,行

    " ldaxrh %w2, %4\n"

    wfe 执行锁的独占加载获取之后。如上一条评论所述,这将用全局监视器标记锁的地址。

    解锁码在同一地址上执行存储释放

    " stlrh %w1, %0\n"

    这将生成事件。这就是为什么他们在锁定功能中使用 load-acquire 来锁定锁定的原因,而不是常规加载,以及解锁时不需要 SEV 的原因。

    【讨论】:

      【解决方案2】:

      即使在标记为独占的内存位置发生存储时,也会清除全局监视器事件。

      参见状态转移图 B2-5。对标记地址的存储将清除全局监视器事件,因此会生成一个事件。这将导致锁定 wfe 完成。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-14
        • 1970-01-01
        • 1970-01-01
        • 2020-08-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多