c - Linux ARM spinlock 中是否存在竞争条件



这是来自arch/arm/include/asm/spinlock.h的自旋锁的Linux实现:

static inline void arch_spin_lock(arch_spinlock_t *lock)
{
    unsigned long tmp;
    u32 newval;
    arch_spinlock_t lockval;
    prefetchw(&lock->slock);
    __asm__ __volatile__(
"1: ldrex   %0, [%3]n"
"   add %1, %0, %4n"
"   strex   %2, %1, [%3]n"
"   teq %2, #0n"
"   bne 1b"
    : "=&r" (lockval), "=&r" (newval), "=&r" (tmp)
    : "r" (&lock->slock), "I" (1 << TICKET_SHIFT)
    : "cc");
    while (lockval.tickets.next != lockval.tickets.owner) {
        wfe();
        lockval.tickets.owner = READ_ONCE(lock->tickets.owner);
    }
    smp_mb();
}
...
static inline void arch_spin_unlock(arch_spinlock_t *lock)
{
    smp_mb();
    lock->tickets.owner++;
    dsb_sev();
}

我担心的是以下两行arch_spin_lock

    while (lockval.tickets.next != lockval.tickets.owner) {
        wfe();

不是原子的。那么,如果arch_spin_unlock被召唤在这两行之间呢?这意味着在函数arch_spin_lock中,WFE指令将被运行,但SEV已经运行并且不会再次运行。因此,在最坏的情况下,arch_spin_lock会永远等待,或者直到一些不相关的事件发生。

这是对的,还是我误解了什么?如果它只是理论上的问题,有没有办法避免这个问题?

我认为您缺少WFE文档的这一点:

如果设置了事件寄存器,WFE 将清除它并立即返回。

在你描述的"竞赛"中WFE将被执行,但会立即返回,然后while循环将退出。

相关内容

  • 没有找到相关文章

最新更新