ThreadSanitizer说我的Atomic Inc / Dec有数据竞争,误报?

时间:2016-03-21 09:22:03

标签: c++ linux multithreading locking

我使用asm编写了我的atomic_inc以增加整数,它实际上用于引用共享对象的计数。 gcc 4.8.2 -fsanitize = thread报告数据竞赛,我终于发现它可能是由我的atomic_inc引起的。我不相信我的代码有一个与数据竞争有关的错误,这是tsan的误报吗?

static inline int atomic_add(volatile int *count, int add) {
    __asm__ __volatile__(
            "lock xadd %0, (%1);"
            : "=a"(add)
            : "r"(count), "a"(add)
            : "memory"
    );
    return add;
}

void MyClass::Ref() {
    // std::unique_lock<std::mutex> lock(s_ref);
    atomic_add(&_refs, 1);
}
void MyClass::Unref() {
    // std::unique_lock<std::mutex> lock(s_ref);
    int n = atomic_add(&_refs, -1) - 1;
    // lock.unlock();
    assert(n >= 0);
    if (n <= 0) {
        delete this;
    }
}

2 个答案:

答案 0 :(得分:2)

你的部分问题是gcc没有查看asm。

问题的另一部分是volatile不会使变量成为线程安全的。

鉴于__asm__意味着你致力于gcc,为什么不使用gcc内在函数? (它们经过记录并经过充分测试,gcc将理解它们的语义。)

至于警告是否是误报,我不知道。安全的做法是假设问题是真的。 真的很难看到多线程代码中的问题(即使你知道他们在那里)。 (一旦我们使用已发布的互斥算法破解了一段非常聪明的代码,并使用简单的自旋锁替换它。这修复了失败,但我们永远无法找到为什么失败。 )

答案 1 :(得分:1)

正如其他人已经说过的那样,该工具无法在你的asm中看到。但无论如何你不应该这样做。 只需使用std :: atomic并完成它 - 这既是线程安全又可移植的,编译器知道如何优化它 - 与当前代码不同。