8#include "time_stamp_count.hpp"
9#include "../utility/utility.hpp"
10#include "../concurrency/concurrency.hpp"
11#include "../macros.hpp"
30 utc_nanoseconds shortest_tp;
34 for (
auto i = 0; i != 10; ++i) {
35 hilet tmp_tsc1 = time_stamp_count::now();
36 hilet tmp_tp = std::chrono::utc_clock::now();
37 hilet tmp_tsc2 = time_stamp_count::now();
39 if (tmp_tsc1.cpu_id() != tmp_tsc2.cpu_id()) {
40 throw os_error(
"CPU Switch detected during get_sample(), which should never happen");
43 if (tmp_tsc1.count() > tmp_tsc2.count()) {
50 hilet diff = tmp_tsc2.count() - tmp_tsc1.count();
52 if (diff < shortest_diff) {
55 shortest_tsc = tmp_tsc1 + (diff / 2);
60 throw os_error(
"Unable to get TSC sample.");
77 auto i = tsc.cpu_id();
79 hilet tsc_epoch = tsc_epochs[i].load(std::memory_order::relaxed);
80 if (tsc_epoch != utc_nanoseconds{}) {
81 return tsc_epoch + tsc.time_since_epoch();
86 hilet ref_tp = std::chrono::utc_clock::now();
87 hilet ref_tsc = time_stamp_count::now();
88 hilet diff_ns = ref_tsc.time_since_epoch() - tsc.time_since_epoch();
89 return ref_tp - diff_ns;
96 return hi::start_subsystem(global_state_type::time_stamp_utc_is_running, init_subsystem, deinit_subsystem);
115 static inline
std::jthread subsystem_thread;
116 static inline unfair_mutex mutex;
117 static inline
std::array<
std::atomic<utc_nanoseconds>, maximum_num_cpus> tsc_epochs = {};
119 static void subsystem_proc_frequency_calibration(std::stop_token stop_token)
121 using namespace std::chrono_literals;
129 for (
auto i = 0; i != frequencies.
size();) {
130 hilet f = time_stamp_count::measure_frequency(1s);
136 if (stop_token.stop_requested()) {
140 std::ranges::sort(frequencies);
141 hilet iqr_size = frequencies.
size() / 2;
143 hilet iqr_last =
std::next(iqr_first, iqr_size);
144 hilet frequency =
std::accumulate(iqr_first, iqr_last, uint64_t{0}) / iqr_size;
146 time_stamp_count::set_frequency(frequency);
148 static void subsystem_proc(std::stop_token stop_token)
150 using namespace std::chrono_literals;
153 subsystem_proc_frequency_calibration(stop_token);
158 while (not stop_token.stop_requested()) {
162 hilet
lock = std::scoped_lock(time_stamp_utc::mutex);
164 time_stamp_count tsc;
165 hilet tp = time_stamp_utc::now(tsc);
166 hi_assert(tsc.cpu_id() == narrow_cast<ssize_t>(current_cpu));
168 tsc_epochs[current_cpu].store(tp - tsc.time_since_epoch(), std::memory_order::relaxed);
174 static bool init_subsystem() noexcept
176 time_stamp_utc::subsystem_thread = std::jthread{subsystem_proc};
182 static void deinit_subsystem() noexcept
185 if (time_stamp_utc::subsystem_thread.joinable()) {
186 time_stamp_utc::subsystem_thread.request_stop();
187 time_stamp_utc::subsystem_thread.join();
192 [[nodiscard]]
static std::size_t find_cpu_id(uint32_t cpu_id)
noexcept;
197 using namespace std::chrono_literals;
199 if (duration >= 1s) {
201 }
else if (duration >= 1
ms) {
203 }
else if (duration >= 1us) {
std::vector< bool > process_affinity_mask()
Get the current process CPU affinity mask.
void set_thread_name(std::string_view name) noexcept
Set the name of the current thread.
T::value_type start_subsystem(T &check_variable, typename T::value_type off_value, typename T::value_type(*init_function)(), void(*deinit_function)())
Start a sub-system.
Definition subsystem.hpp:116
bool global_state_disable(global_state_type subsystem, std::memory_order order=std::memory_order::seq_cst) noexcept
Disable a subsystem.
Definition global_state.hpp:247
std::size_t advance_thread_affinity(std::size_t &cpu) noexcept
Advance thread affinity to the next CPU.
Definition thread_intf.hpp:122
void stop_subsystem(void(*deinit_function)())
Stop a sub-system.
Definition subsystem.hpp:202
DOXYGEN BUG.
Definition algorithm.hpp:16
constexpr Out narrow_cast(In const &rhs) noexcept
Cast numeric values without loss of precision.
Definition cast.hpp:377
Since Window's 10 QueryPerformanceCounter() counts at only 10MHz which is too low to measure performa...
Definition time_stamp_count.hpp:31
Timestamp.
Definition time_stamp_utc.hpp:22
static void stop_subsystem() noexcept
This will stop the calibration subsystem.
Definition time_stamp_utc.hpp:101
static bool start_subsystem() noexcept
This will start the calibration subsystem.
Definition time_stamp_utc.hpp:94
static utc_nanoseconds make(time_stamp_count const &tsc) noexcept
Make a time point from a time stamp count.
Definition time_stamp_utc.hpp:75
static utc_nanoseconds now(time_stamp_count &tsc)
Get the current time and TSC value.
Definition time_stamp_utc.hpp:26
static void adjust_for_drift() noexcept
A calibration step which will drift the per-cpu tsc-offset.