utils: Make get_tsc_freq() inlined and non-blocking

This commit is contained in:
elad335 2024-10-24 13:01:40 +03:00 committed by Elad
parent 2e8029a45b
commit c70c08bb07
3 changed files with 27 additions and 9 deletions

View file

@ -554,7 +554,7 @@ int main(int argc, char** argv)
ensure(thread_ctrl::is_main(), "Not main thread"); ensure(thread_ctrl::is_main(), "Not main thread");
// Initialize TSC freq (in case it isn't) // Initialize TSC freq (in case it isn't)
static_cast<void>(utils::get_tsc_freq()); static_cast<void>(utils::ensure_tsc_freq_init());
// Initialize thread pool finalizer (on first use) // Initialize thread pool finalizer (on first use)
static_cast<void>(named_thread("", [](int) {})); static_cast<void>(named_thread("", [](int) {}));

View file

@ -739,7 +739,12 @@ static constexpr ullong round_tsc(ullong val)
return utils::rounded_div(val, 1'000'000) * 1'000'000; return utils::rounded_div(val, 1'000'000) * 1'000'000;
} }
ullong utils::get_tsc_freq() namespace utils
{
u64 s_tsc_freq = 0;
}
named_thread<std::function<void()>> s_thread_evaluate_tsc_freq("TSX Evaluate Thread", []()
{ {
static const ullong cal_tsc = []() -> ullong static const ullong cal_tsc = []() -> ullong
{ {
@ -749,7 +754,7 @@ ullong utils::get_tsc_freq()
return r; return r;
#endif #endif
if (!has_invariant_tsc()) if (!utils::has_invariant_tsc())
return 0; return 0;
#ifdef _WIN32 #ifdef _WIN32
@ -766,7 +771,7 @@ ullong utils::get_tsc_freq()
#endif #endif
// Calibrate TSC // Calibrate TSC
constexpr int samples = 40; constexpr int samples = 60;
ullong rdtsc_data[samples]; ullong rdtsc_data[samples];
ullong timer_data[samples]; ullong timer_data[samples];
[[maybe_unused]] ullong error_data[samples]; [[maybe_unused]] ullong error_data[samples];
@ -784,14 +789,14 @@ ullong utils::get_tsc_freq()
for (int i = 0; i < samples; i++) for (int i = 0; i < samples; i++)
{ {
#ifdef _WIN32 #ifdef _WIN32
Sleep(1); Sleep(2);
error_data[i] = (utils::lfence(), utils::get_tsc()); error_data[i] = (utils::lfence(), utils::get_tsc());
LARGE_INTEGER ctr; LARGE_INTEGER ctr;
QueryPerformanceCounter(&ctr); QueryPerformanceCounter(&ctr);
rdtsc_data[i] = (utils::lfence(), utils::get_tsc()); rdtsc_data[i] = (utils::lfence(), utils::get_tsc());
timer_data[i] = ctr.QuadPart; timer_data[i] = ctr.QuadPart;
#else #else
usleep(200); usleep(500);
error_data[i] = (utils::lfence(), utils::get_tsc()); error_data[i] = (utils::lfence(), utils::get_tsc());
struct timespec ts; struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts); clock_gettime(CLOCK_MONOTONIC, &ts);
@ -814,7 +819,13 @@ ullong utils::get_tsc_freq()
return round_tsc(acc / (samples - 1)); return round_tsc(acc / (samples - 1));
}(); }();
return cal_tsc; atomic_storage<u64>::release(utils::s_tsc_freq, cal_tsc);
});
void utils::ensure_tsc_freq_init()
{
// Join thread
s_thread_evaluate_tsc_freq();
} }
u64 utils::get_total_memory() u64 utils::get_total_memory()

View file

@ -73,8 +73,6 @@ namespace utils
bool get_low_power_mode(); bool get_low_power_mode();
ullong get_tsc_freq();
u64 get_total_memory(); u64 get_total_memory();
u32 get_thread_count(); u32 get_thread_count();
@ -89,4 +87,13 @@ namespace utils
u64 _get_main_tid(); u64 _get_main_tid();
inline const u64 main_tid = _get_main_tid(); inline const u64 main_tid = _get_main_tid();
extern u64 s_tsc_freq;
inline ullong get_tsc_freq()
{
return s_tsc_freq;
}
void ensure_tsc_freq_init();
} }