Make explicitly racy part of stack

The MPMCStack has a race that is necessary for implementing optimistic
non-blocking data-structures.  This commit makes TSAN ignore this race.
This commit is contained in:
Matthew Parkinson
2021-12-17 12:29:42 +00:00
committed by Matthew Parkinson
parent 84ac360445
commit 16875382c4

View File

@@ -3,6 +3,12 @@
#include "aba.h"
#include "ptrwrap.h"
#if defined(__has_feature)
# if __has_feature(thread_sanitizer)
# define SNMALLOC_THREAD_SANITIZER_ENABLED
# endif
#endif
namespace snmalloc
{
template<class T, Construction c = RequiresInit>
@@ -13,6 +19,22 @@ namespace snmalloc
private:
alignas(CACHELINE_SIZE) ABAT stack;
#ifdef SNMALLOC_THREAD_SANITIZER_ENABLED
__attribute__((no_sanitize("thread"))) static T*
racy_read(std::atomic<T*>& ptr)
{
// reinterpret_cast is required as TSAN still instruments
// std::atomic operations, even if you disable TSAN on
// the function.
return *reinterpret_cast<T**>(&ptr);
}
#else
static T* racy_read(std::atomic<T*>& ptr)
{
return ptr.load(std::memory_order_relaxed);
}
#endif
public:
constexpr MPMCStack() = default;
@@ -52,7 +74,11 @@ namespace snmalloc
if (top == nullptr)
break;
next = top->next.load(std::memory_order_acquire);
// The following read can race with non-atomic accesses
// this is undefined behaviour. There is no way to use
// CAS sensibly that conforms to the standard with optimistic
// concurrency.
next = racy_read(top->next);
} while (!cmp.store_conditional(next));
return top;