【问题标题】:ThreadSanitizer says my spin_lock has data race, but how?ThreadSanitizer 说我的 spin_lock 有数据竞争,但是怎么办?
【发布时间】:2016-03-21 03:15:08
【问题描述】:

我的自旋锁实现如下所示,我认为它不会导致任何数据竞争,但是当我使用 -fsanitize=thread 测试我的代码时,它报告 spin_unlock 有写入数据竞争。这怎么可能发生?是误报吗?

#define barrier() asm volatile("": : :"memory")
#define cpu_relax() asm volatile("pause\n": : :"memory")

static inline void spin_lock(volatile int *lock) {
    while (1)
    {
        int i = 0;
        if (!atomic_swap(lock, EBUSY)) return;
        while (*lock) {
            i++;
            if (i == 4000) {
                i = 0;
                thread_yield();
            }
            cpu_relax();
        }
    }
}

static inline void spin_unlock(volatile int *lock) {
    barrier();
    *lock = 0;
}

atomic_swap 是一个函数:

static inline int atomic_swap(volatile void *lockword, int value) {
    unsigned long tmp;
    int result;
    __asm__ __volatile__ ("dmb" : : : "memory");
    __asm__ __volatile__("@ atomic_swap\n"
    "1: ldrex   %0, [%2]\n"
    "   strex   %1, %3, [%2]\n"
    "   teq %1, #0\n"
    "   bne 1b"
    : "=&r" (result), "=&r" (tmp)
    : "r" (lockword), "Ir" (value)
    : "cc");

    __asm__ __volatile__ ("dmb" : : : "memory");
    return result;
}

【问题讨论】:

  • 我对 ARM 一无所知,但我对竞态条件知之甚少。我怀疑您的问题是您没有检查 ldrex 中返回的值。在您的循环中检查lock,但有可能在thread1 看到它变为0 和ldrex 返回值之间,thread2 可能突然介入并更改了它。所以2个线程都会写EBUSY。可能不是你想要的。
  • 另外,您正在更改内存中的值(锁定字),但没有将其列为输出。考虑将[%2] 更改为%2,将其从输入移至输出,并将其约束更改为+m
  • 它在 intex x64 平台上,在 ARM 上没有。
  • 我不相信“intex”是一个“平台”。 Intex 销售 [手机](www.intex.in/mobiles/smart-phones/)(即 aqua 智能手机)-> 他们的手机包含处理器(即 Snapdragon 615)。 Snapdragon 处理器是一个 ARM 平台。 ldrexstrex & dmb 都是针对 ARM 平台的指令。但即使我错了,您似乎很清楚您正在从内存中加载一个值 (ldrex %0, [%2]),但没有检查该值是什么。您只是“希望”在执行 while (*lock) 和执行 ldrex 之间没有任何改变。这是一个竞争条件。

标签: c++ linux multithreading crash locking


【解决方案1】:

ThreadSanitizer 不知道您自己开发的 atomic_swap()barrier() 函数的语义。来自ThreadSanitizer FAQ

问:支持哪些同步原语? TSan 支持 pthread 同步原语,内置编译器原子操作(同步/原子),llvm libc++ 支持 C++ 操作(不是很彻底 [原文如此]不过经过测试)。

所以它不知道atomic_swap() 应该做什么,除此之外ThreadSanitizer currently doesn't support memory fences

【讨论】:

    猜你喜欢
    • 2016-07-07
    • 2022-08-20
    • 2022-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多