moved tsc and asm utilities to rx

This commit is contained in:
DH 2025-10-05 19:28:03 +03:00
parent bd215fab92
commit 640df36c48
121 changed files with 706 additions and 1225 deletions

View file

@ -6,19 +6,10 @@
#include <functional>
#include <limits>
#include <system_error>
#include <thread>
#include <type_traits>
#include "asm.hpp"
namespace rx {
inline void yield() { std::this_thread::yield(); }
inline void relax() {
#if defined(__GNUC__) && (defined __i386__ || defined __x86_64__)
__builtin_ia32_pause();
#else
yield();
#endif
}
static constexpr auto kRelaxSpinCount = 12;
static constexpr auto kSpinCount = 16;
@ -31,7 +22,7 @@ bool try_spin_wait(auto &&pred) {
}
if (i < kRelaxSpinCount) {
relax();
pause();
} else {
yield();
}

View file

@ -1,14 +1,21 @@
#pragma once
#include <cstdint>
#include <type_traits>
namespace rx {
inline constexpr std::uint64_t alignUp(std::uint64_t value,
std::uint64_t alignment) {
return (value + (alignment - 1)) & ~(alignment - 1);
template <typename T, typename U>
requires std::is_unsigned_v<T>
inline constexpr std::make_unsigned_t<std::common_type_t<T, U>>
alignUp(T value, U alignment) {
return static_cast<std::make_unsigned_t<std::common_type_t<T, U>>>(
(value + (alignment - 1)) & ~(alignment - 1));
}
inline constexpr std::uint64_t alignDown(std::uint64_t value,
std::uint64_t alignment) {
return value & ~(alignment - 1);
template <typename T, typename U>
requires std::is_unsigned_v<T>
inline constexpr std::make_unsigned_t<std::common_type_t<T, U>>
alignDown(T value, U alignment) {
return static_cast<std::make_unsigned_t<std::common_type_t<T, U>>>(
value & ~(alignment - 1));
}
} // namespace rx

View file

@ -1,6 +1,8 @@
#pragma once
#include "rx/tsc.hpp"
#include "types.hpp"
#include <thread>
#include <atomic>
extern bool g_use_rtm;
@ -275,6 +277,16 @@ inline void pause() {
#endif
}
inline void yield() { std::this_thread::yield(); }
// Synchronization helper (cache-friendly busy waiting)
inline void busy_wait(usz cycles = 3000) {
const u64 stop = get_tsc() + cycles;
do
pause();
while (get_tsc() < stop);
}
// Align to power of 2
template <typename T, typename U>
requires std::is_unsigned_v<T>
@ -312,12 +324,6 @@ constexpr T rational_mul(T value, std::type_identity_t<T> numerator,
return static_cast<T>(value * u64{numerator} / u64{denominator});
}
#if is_u128_emulated
if constexpr (sizeof(T) <= sizeof(u128) / 2) {
return static_cast<T>(u128_from_mul(value, numerator) / u64{denominator});
}
#endif
return static_cast<T>(value / denominator * numerator +
(value % denominator) * numerator / denominator);
}

28
rx/include/rx/tsc.hpp Normal file
View file

@ -0,0 +1,28 @@
#pragma once
#include "types.hpp"
#include <cstdint>
#ifdef _M_X64
#ifdef _MSC_VER
extern "C" std::uint64_t __rdtsc();
#else
#include <immintrin.h>
#endif
#endif
namespace rx {
inline std::uint64_t get_tsc() {
#if defined(ARCH_ARM64)
std::uint64_t r = 0;
__asm__ volatile("mrs %0, cntvct_el0" : "=r"(r));
return r;
#elif defined(_M_X64)
return __rdtsc();
#elif defined(ARCH_X64)
return __builtin_ia32_rdtsc();
#else
#error "Missing rx::get_tsc() implementation"
#endif
}
} // namespace rx

View file

@ -106,20 +106,6 @@ template <typename F> fn_helper(F &&f) -> fn_helper<F>;
[[maybe_unused]] auto &&z, \
[[maybe_unused]] auto &&w) { return (__VA_ARGS__); })
#if __cpp_lib_bit_cast < 201806L
namespace std {
template <typename To, typename From>
[[nodiscard]] constexpr To bit_cast(const From &from) noexcept {
return __builtin_bit_cast(To, from);
}
} // namespace std
#endif
#if defined(__INTELLISENSE__) || (defined(__clang__) && (__clang_major__ <= 16))
#define consteval constexpr
#define constinit
#endif
// FIXME: move to ps3 kernel implementation
using schar = signed char;
using uchar = unsigned char;
@ -206,9 +192,9 @@ public:
};
#if defined(ARCH_X64) && !defined(_MSC_VER)
using __m128i = long long __attribute__((vector_size(16)));
using __m128d = double __attribute__((vector_size(16)));
using __m128 = float __attribute__((vector_size(16)));
using __m128i = long long __attribute__((vector_size(16), aligned(16)));
using __m128d = double __attribute__((vector_size(16), aligned(16)));
using __m128 = float __attribute__((vector_size(16), aligned(16)));
#endif
#ifndef _MSC_VER

View file

@ -1,14 +1,7 @@
#include "SharedMutex.hpp"
#include "asm.hpp"
#include <syscall.h>
#include <unistd.h>
#include <xmmintrin.h>
static void busy_wait(unsigned long long cycles = 3000) {
const auto stop = __builtin_ia32_rdtsc() + cycles;
do
_mm_pause();
while (__builtin_ia32_rdtsc() < stop);
}
namespace rx {
void shared_mutex::impl_lock_shared(unsigned val) {