Use atomics in CpuInfo::host()

The code was fine, however, some compilers may be able to optimize
it and in some border cases the features returned would be all zero.
This prevents such behavior.
This commit is contained in:
kobalicek
2024-02-10 21:56:59 +01:00
parent 9e39b1e814
commit d82e478fb8
2 changed files with 19 additions and 15 deletions

View File

@@ -7,6 +7,8 @@
#include "../core/cpuinfo.h"
#include "../core/support.h"
#include <atomic>
// Required by `__cpuidex()` and `_xgetbv()`.
#if ASMJIT_ARCH_X86
#if defined(_MSC_VER)
@@ -1969,13 +1971,13 @@ static ASMJIT_FAVOR_SIZE void detectARMCpu(CpuInfo& cpu) noexcept {
// CpuInfo - Detect - Host
// =======================
static uint32_t cpuInfoInitialized;
static CpuInfo cpuInfoGlobal(Globals::NoInit);
const CpuInfo& CpuInfo::host() noexcept {
// This should never cause a problem as the resulting information should always be the same.
// In the worst case it would just be overwritten non-atomically.
if (!cpuInfoInitialized) {
static std::atomic<uint32_t> cpuInfoInitialized;
static CpuInfo cpuInfoGlobal(Globals::NoInit);
// This should never cause a problem as the resulting information should always
// be the same. In the worst case it would just be overwritten non-atomically.
if (!cpuInfoInitialized.load(std::memory_order_relaxed)) {
CpuInfo cpuInfoLocal;
cpuInfoLocal._arch = Arch::kHost;
@@ -1989,7 +1991,7 @@ const CpuInfo& CpuInfo::host() noexcept {
cpuInfoLocal._hwThreadCount = detectHWThreadCount();
cpuInfoGlobal = cpuInfoLocal;
cpuInfoInitialized = 1;
cpuInfoInitialized.store(1, std::memory_order_seq_cst);
}
return cpuInfoGlobal;

View File

@@ -22,11 +22,6 @@ ASMJIT_BEGIN_NAMESPACE
//! Each feature is represented by a single bit in an embedded bit array.
class CpuFeatures {
public:
//! A word that is used to represents feature bits.
typedef Support::BitWord BitWord;
//! Iterator that can iterate all CPU features set.
typedef Support::BitVectorIterator<BitWord> Iterator;
//! \name Constants
//! \{
@@ -37,6 +32,13 @@ public:
};
//! \endcond
//! A word that is used to represents feature bits.
typedef Support::BitWord BitWord;
//! Iterator that can iterate all CPU features set.
typedef Support::BitVectorIterator<BitWord> Iterator;
typedef Support::Array<BitWord, kNumBitWords> Bits;
//! \}
//! \name Data
@@ -48,7 +50,7 @@ public:
//! \{
//! Data bits.
Support::Array<BitWord, kNumBitWords> _bits;
Bits _bits;
//! \}
@@ -178,8 +180,7 @@ public:
#endif // !ASMJIT_NO_DEPRECATED
//! \}
};
};
//! X86 specific features data.
struct X86 : public Data {
@@ -948,6 +949,7 @@ public:
ASMJIT_INLINE_NODEBUG CpuFeatures() noexcept {}
ASMJIT_INLINE_NODEBUG CpuFeatures(const CpuFeatures& other) noexcept = default;
ASMJIT_INLINE_NODEBUG explicit CpuFeatures(const Data& other) noexcept : _data{other._bits} {}
ASMJIT_INLINE_NODEBUG explicit CpuFeatures(Globals::NoInit_) noexcept {}
//! \}