Skip to content

Commit 67b4efc

Browse files
committed
[Support/BLAKE3] Make g_cpu_features thread safe
`g_cpu_features` can be updated multiple times by `get_cpu_features()`, which reports a thread sanitizer error when used with multiple lld threads.
1 parent 535d691 commit 67b4efc

File tree

1 file changed

+37
-5
lines changed

1 file changed

+37
-5
lines changed

llvm/lib/Support/BLAKE3/blake3_dispatch.c

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,36 @@
1414
#endif
1515
#endif
1616

17+
/* Atomic access abstraction (since MSVC does not do C11 yet) */
18+
#if defined(_MSC_VER) && !defined(__clang__)
19+
#if !defined(IS_X86)
20+
#include <intrin.h>
21+
#endif
22+
#pragma warning(disable : 5105)
23+
#ifndef FORCEINLINE
24+
#define FORCEINLINE inline __forceinline
25+
#endif
26+
typedef volatile long atomic32_t;
27+
static FORCEINLINE int32_t atomic_load32(atomic32_t *src) {
28+
return _InterlockedOr(src, 0);
29+
}
30+
static FORCEINLINE void atomic_store32(atomic32_t *dst, int32_t val) {
31+
_InterlockedExchange(dst, val);
32+
}
33+
#else
34+
#include <stdatomic.h>
35+
#ifndef FORCEINLINE
36+
#define FORCEINLINE inline __attribute__((__always_inline__))
37+
#endif
38+
typedef volatile _Atomic(int32_t) atomic32_t;
39+
static FORCEINLINE int32_t atomic_load32(atomic32_t *src) {
40+
return atomic_load_explicit(src, memory_order_relaxed);
41+
}
42+
static FORCEINLINE void atomic_store32(atomic32_t *dst, int32_t val) {
43+
atomic_store_explicit(dst, val, memory_order_relaxed);
44+
}
45+
#endif
46+
1747
#define MAYBE_UNUSED(x) (void)((x))
1848

1949
#if defined(IS_X86)
@@ -76,17 +106,18 @@ enum cpu_feature {
76106
#if !defined(BLAKE3_TESTING)
77107
static /* Allow the variable to be controlled manually for testing */
78108
#endif
79-
enum cpu_feature g_cpu_features = UNDEFINED;
109+
atomic32_t g_cpu_features = UNDEFINED;
80110

81111
LLVM_ATTRIBUTE_USED
82112
#if !defined(BLAKE3_TESTING)
83113
static
84114
#endif
85115
enum cpu_feature
86116
get_cpu_features(void) {
87-
88-
if (g_cpu_features != UNDEFINED) {
89-
return g_cpu_features;
117+
enum cpu_feature _cpu_features;
118+
_cpu_features = (enum cpu_feature)atomic_load32(&g_cpu_features);
119+
if (_cpu_features != UNDEFINED) {
120+
return _cpu_features;
90121
} else {
91122
#if defined(IS_X86)
92123
uint32_t regs[4] = {0};
@@ -125,10 +156,11 @@ static
125156
}
126157
}
127158
}
128-
g_cpu_features = features;
159+
atomic_store32(&g_cpu_features, (int32_t)features);
129160
return features;
130161
#else
131162
/* How to detect NEON? */
163+
atomic_store32(&g_cpu_features, 0);
132164
return 0;
133165
#endif
134166
}

0 commit comments

Comments
 (0)