diff --git a/file/filename.cc b/file/filename.cc index 968adbaa7..0ac4e6ef8 100644 --- a/file/filename.cc +++ b/file/filename.cc @@ -461,8 +461,8 @@ Status GetInfoLogFiles(Env* env, const std::string& db_log_dir, std::string NormalizePath(const std::string& path) { std::string dst; for (auto c : path) { - if (!dst.empty() && c == kFilePathSeparator && - dst.back() == kFilePathSeparator) { + if (!dst.empty() && (c == kFilePathSeparator || c == '/') && + (dst.back() == kFilePathSeparator || dst.back() == '/')) { continue; } dst.push_back(c); diff --git a/port/win/port_win.cc b/port/win/port_win.cc index 2d99a7a9b..34f6b28de 100644 --- a/port/win/port_win.cc +++ b/port/win/port_win.cc @@ -100,6 +100,14 @@ bool CondVar::TimedWait(uint64_t abs_time_us) { // Caller must ensure that mutex is held prior to calling this method std::unique_lock lk(mu_->getLock(), std::adopt_lock); + + // Work around https://github.com/microsoft/STL/issues/369 +#if defined(_MSC_VER) && (!defined(_MSVC_STL_UPDATE) || _MSVC_STL_UPDATE < 202008L) + if (relTimeUs == microseconds::zero()) { + lk.unlock(); + lk.lock(); + } +#endif #ifndef NDEBUG mu_->locked_ = false; #endif diff --git a/port/win/port_win.h b/port/win/port_win.h index a3ffd559c..2c5b8ff05 100644 --- a/port/win/port_win.h +++ b/port/win/port_win.h @@ -283,7 +283,7 @@ extern const size_t kPageSize; #endif static inline void AsmVolatilePause() { -#if defined(_M_IX86) || defined(_M_X64) +#if defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM64) || defined(_M_ARM) YieldProcessor(); #endif // it would be nice to get "wfe" on ARM here diff --git a/third-party/folly/folly/chrono/Hardware.h b/third-party/folly/folly/chrono/Hardware.h index ec7be82e8..6635b8717 100644 --- a/third-party/folly/folly/chrono/Hardware.h +++ b/third-party/folly/folly/chrono/Hardware.h @@ -10,7 +10,7 @@ #include #include -#if _MSC_VER +#if _MSC_VER && (defined(_M_IX86) || defined(_M_X64)) extern "C" std::uint64_t __rdtsc(); #pragma intrinsic(__rdtsc) #endif @@ -18,7 +18,7 @@ extern "C" std::uint64_t __rdtsc(); namespace folly { inline std::uint64_t hardware_timestamp() { -#if _MSC_VER +#if _MSC_VER && (defined(_M_IX86) || defined(_M_X64)) return __rdtsc(); #elif __GNUC__ && (__i386__ || FOLLY_X64) return __builtin_ia32_rdtsc(); diff --git a/util/math.h b/util/math.h index 64cdb2f44..514943164 100644 --- a/util/math.h +++ b/util/math.h @@ -13,24 +13,75 @@ namespace ROCKSDB_NAMESPACE { +#if defined(_MSC_VER) && !defined(_M_X64) +namespace detail { +template +int BitsSetToOneFallback(T v) { + const int kBits = static_cast(sizeof(T)) * 8; + static_assert((kBits & (kBits - 1)) == 0, "must be power of two bits"); + // we static_cast these bit patterns in order to truncate them to the correct size + v = static_cast(v - ((v >> 1) & static_cast(0x5555555555555555ull))); + v = static_cast((v & static_cast(0x3333333333333333ull)) + + ((v >> 2) & static_cast(0x3333333333333333ull))); + v = static_cast((v + (v >> 4)) & static_cast(0x0F0F0F0F0F0F0F0Full)); + for (int shift_bits = 8; shift_bits < kBits; shift_bits <<= 1) { + v += static_cast(v >> shift_bits); + } + // we want the bottom "slot" that's big enough to store kDigits + // (and including) kBits. + return static_cast(v & static_cast(kBits | (kBits - 1))); +} + +} // namespace detail +#endif + +// Number of bits set to 1. Also known as "population count". template inline int BitsSetToOne(T v) { static_assert(std::is_integral::value, "non-integral type"); #ifdef _MSC_VER static_assert(sizeof(T) <= sizeof(uint64_t), "type too big"); - if (sizeof(T) > sizeof(uint32_t)) { - return static_cast(__popcnt64(static_cast(v))); - } else { + if (sizeof(T) < sizeof(uint32_t)) { + // This bit mask is to avoid a compiler warning on unused path + constexpr auto mm = 8 * sizeof(uint32_t) - 1; + // The bit mask is to neutralize sign extension on small signed types + constexpr uint32_t m = (uint32_t{1} << ((8 * sizeof(T)) & mm)) - 1; +#if defined(_M_X64) || defined(_M_IX86) + return static_cast(__popcnt(static_cast(v) & m)); +#else + return static_cast(detail::BitsSetToOneFallback(v) & m); +#endif + } else if (sizeof(T) == sizeof(uint32_t)) { +#if defined(_M_X64) || defined(_M_IX86) return static_cast(__popcnt(static_cast(v))); +#else + return detail::BitsSetToOneFallback(static_cast(v)); +#endif + } else { +#ifdef _M_X64 + return static_cast(__popcnt64(static_cast(v))); +#elif defined(_M_IX86) + return static_cast( + __popcnt(static_cast(static_cast(v) >> 32) + + __popcnt(static_cast(v)))); +#else + return detail::BitsSetToOneFallback(static_cast(v)); +#endif } #else static_assert(sizeof(T) <= sizeof(unsigned long long), "type too big"); - if (sizeof(T) > sizeof(unsigned long)) { - return __builtin_popcountll(static_cast(v)); - } else if (sizeof(T) > sizeof(unsigned int)) { + if (sizeof(T) < sizeof(unsigned int)) { + // This bit mask is to avoid a compiler warning on unused path + constexpr auto mm = 8 * sizeof(unsigned int) - 1; + // This bit mask is to neutralize sign extension on small signed types + constexpr unsigned int m = (1U << ((8 * sizeof(T)) & mm)) - 1; + return __builtin_popcount(static_cast(v) & m); + } else if (sizeof(T) == sizeof(unsigned int)) { + return __builtin_popcount(static_cast(v)); + } else if (sizeof(T) <= sizeof(unsigned long)) { return __builtin_popcountl(static_cast(v)); } else { - return __builtin_popcount(static_cast(v)); + return __builtin_popcountll(static_cast(v)); } #endif } diff --git a/util/xxh3p.h b/util/xxh3p.h index d1fc2bba2..c63f0e36d 100644 --- a/util/xxh3p.h +++ b/util/xxh3p.h @@ -253,7 +253,7 @@ XXH_FORCE_INLINE U64x2 XXH_vec_mule(U32x4 a, U32x4 b) { #if defined(XXH_NO_PREFETCH) # define XXH_PREFETCH(ptr) (void)(ptr) /* disabled */ #else -# if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86)) /* _mm_prefetch() is not defined outside of x86/x64 */ +# if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86)) /* _mm_prefetch() is not defined outside of x86/x64 */ # include /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */ # define XXH_PREFETCH(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T0) # elif defined(__GNUC__) && ( (__GNUC__ >= 4) || ( (__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) ) )