【问题标题】:Race condition on ticket-based ARM spinlock基于票证的 ARM 自旋锁的竞争条件
【发布时间】:2013-11-14 13:34:23
【问题描述】:

我发现Linux内核中的自旋锁现在都在使用“ticket-based”自旋锁。然而,在查看了它的 ARM 实现之后,我很困惑,因为“加载-添加-存储”操作根本不是原子的。请看下面的代码:

 74 static inline void arch_spin_lock(arch_spinlock_t *lock)
 75 {
 76         unsigned long tmp;
 77         u32 newval;
 78         arch_spinlock_t lockval;
 79 
 80         __asm__ __volatile__(
 81 "1:     ldrex   %0, [%3]\n"   /*Why this load-add-store is not atomic?*/
 82 "       add     %1, %0, %4\n"
 83 "       strex   %2, %1, [%3]\n"
 84 "       teq     %2, #0\n"
 85 "       bne     1b"
 86         : "=&r" (lockval), "=&r" (newval), "=&r" (tmp)
 87         : "r" (&lock->slock), "I" (1 << TICKET_SHIFT)
 88         : "cc");
 89 
 90         while (lockval.tickets.next != lockval.tickets.owner) {
 91                 wfe();
 92                 lockval.tickets.owner = ACCESS_ONCE(lock->tickets.owner);
 93         }
 94 
 95         smp_mb();
 96 }

如您所见,在第 81~83 行,它将 lock->slock 加载到“lockval”并将其加一,然后将其存储回 lock->slock。

但是我没有看到任何地方可以确保它是原子的。所以有可能:

不同cpu上的两个用户同时读取lock->slock到他们自己的变量“lockval”;然后他们分别将“lockval”加一,然后将其存储回来。

这将导致这两个用户手头有相同的“数字”,一旦“所有者”字段变为该数字,他们都会获得锁并对某些共享资源进行操作!

我认为内核在自旋锁中不可能有这样的错误。我是不是哪里错了?

【问题讨论】:

    标签: linux multithreading


    【解决方案1】:

    STREX is a conditional store,此代码具有 Load Link-Store Conditional 语义,即使 ARM 不使用该名称。

    操作要么自动完成,要么失败。

    汇编程序块测试失败(tmp 变量表示失败)并使用新值(由另一个内核更新)重新尝试修改。

    【讨论】:

    • 我明白了。所以锁定仍然发生在处理器指令中。谢谢。
    猜你喜欢
    • 2019-11-30
    • 2020-10-17
    • 2014-11-08
    • 1970-01-01
    • 1970-01-01
    • 2012-04-17
    • 1970-01-01
    • 1970-01-01
    • 2012-10-27
    相关资源
    最近更新 更多