diff --git a/src/common/utils/timer.hpp b/src/common/utils/timer.hpp index 22120bce..35f6592c 100644 --- a/src/common/utils/timer.hpp +++ b/src/common/utils/timer.hpp @@ -2,6 +2,10 @@ #include +constexpr auto HUNDRED_NANOSECONDS_IN_ONE_SECOND = 10000000LL; +constexpr auto EPOCH_DIFFERENCE_1601_TO_1970_SECONDS = 11644473600LL; +constexpr auto WINDOWS_EPOCH_DIFFERENCE = EPOCH_DIFFERENCE_1601_TO_1970_SECONDS * HUNDRED_NANOSECONDS_IN_ONE_SECOND; + namespace utils { template @@ -23,4 +27,78 @@ namespace utils private: typename Clock::time_point point_{Clock::now()}; }; + + inline std::chrono::steady_clock::time_point convert_delay_interval_to_time_point(const LARGE_INTEGER delay_interval) + { + if (delay_interval.QuadPart <= 0) + { + const auto relative_time = -delay_interval.QuadPart; + const auto relative_ticks_in_ms = relative_time / 10; + const auto relative_fraction_ns = (relative_time % 10) * 100; + const auto relative_duration = + std::chrono::microseconds(relative_ticks_in_ms) + std::chrono::nanoseconds(relative_fraction_ns); + + return std::chrono::steady_clock::now() + relative_duration; + } + + const auto delay_seconds_since_1601 = delay_interval.QuadPart / HUNDRED_NANOSECONDS_IN_ONE_SECOND; + const auto delay_fraction_ns = (delay_interval.QuadPart % HUNDRED_NANOSECONDS_IN_ONE_SECOND) * 100; + + const auto delay_seconds_since_1970 = delay_seconds_since_1601 - EPOCH_DIFFERENCE_1601_TO_1970_SECONDS; + + const auto target_time = + std::chrono::system_clock::from_time_t(delay_seconds_since_1970) + std::chrono::nanoseconds(delay_fraction_ns); + + const auto now_system = std::chrono::system_clock::now(); + + const auto duration_until_target = std::chrono::duration_cast(target_time - now_system); + + return std::chrono::steady_clock::now() + duration_until_target; + } + + inline KSYSTEM_TIME convert_to_ksystem_time(const std::chrono::system_clock::time_point& tp) + { + const auto duration = tp.time_since_epoch(); + const auto ns_duration = std::chrono::duration_cast(duration); + + const auto total_ticks = ns_duration.count() / 100 + WINDOWS_EPOCH_DIFFERENCE; + + KSYSTEM_TIME time{}; + time.LowPart = static_cast(total_ticks); + time.High1Time = static_cast(total_ticks >> 32); + time.High2Time = time.High1Time; + + return time; + } + + inline void convert_to_ksystem_time(volatile KSYSTEM_TIME* dest, const std::chrono::system_clock::time_point& tp) + { + const auto time = convert_to_ksystem_time(tp); + memcpy(const_cast(dest), &time, sizeof(*dest)); + } + + inline std::chrono::system_clock::time_point convert_from_ksystem_time(const KSYSTEM_TIME& time) + { + auto totalTicks = (static_cast(time.High1Time) << 32) | time.LowPart; + totalTicks -= WINDOWS_EPOCH_DIFFERENCE; + + const auto duration = std::chrono::system_clock::duration(totalTicks * 100); + return std::chrono::system_clock::time_point(duration); + } + + inline std::chrono::system_clock::time_point convert_from_ksystem_time(const volatile KSYSTEM_TIME& time) + { + return convert_from_ksystem_time(*const_cast(&time)); + } + +#ifndef OS_WINDOWS + using __time64_t = int64_t; +#endif + + inline LARGE_INTEGER convert_unix_to_windows_time(const __time64_t unix_time) + { + LARGE_INTEGER windows_time{}; + windows_time.QuadPart = (unix_time + EPOCH_DIFFERENCE_1601_TO_1970_SECONDS) * HUNDRED_NANOSECONDS_IN_ONE_SECOND; + return windows_time; + } } diff --git a/src/windows-emulator/devices/afd_endpoint.cpp b/src/windows-emulator/devices/afd_endpoint.cpp index 6b431881..6d2661bb 100644 --- a/src/windows-emulator/devices/afd_endpoint.cpp +++ b/src/windows-emulator/devices/afd_endpoint.cpp @@ -2,12 +2,12 @@ #include "afd_types.hpp" #include "../windows_emulator.hpp" -#include "../syscall_utils.hpp" #include #include #include +#include namespace { @@ -410,7 +410,7 @@ namespace std::optional timeout{}; if (info.Timeout.QuadPart != std::numeric_limits::max()) { - timeout = convert_delay_interval_to_time_point(info.Timeout); + timeout = utils::convert_delay_interval_to_time_point(info.Timeout); } this->delay_ioctrl(c, timeout); diff --git a/src/windows-emulator/kusd_mmio.cpp b/src/windows-emulator/kusd_mmio.cpp index d8f6176c..a2ad2c2a 100644 --- a/src/windows-emulator/kusd_mmio.cpp +++ b/src/windows-emulator/kusd_mmio.cpp @@ -1,5 +1,5 @@ #include "kusd_mmio.hpp" -#include "syscall_utils.hpp" +#include #include "windows_emulator.hpp" #include @@ -123,7 +123,7 @@ void kusd_mmio::setup(const bool use_relative_time) this->use_relative_time_ = use_relative_time; setup_kusd(this->kusd_, use_relative_time); - this->start_time_ = convert_from_ksystem_time(this->kusd_.SystemTime); + this->start_time_ = utils::convert_from_ksystem_time(this->kusd_.SystemTime); this->register_mmio(); } @@ -193,7 +193,7 @@ void kusd_mmio::update() time = std::chrono::system_clock::now(); } - convert_to_ksystem_time(&this->kusd_.SystemTime, time); + utils::convert_to_ksystem_time(&this->kusd_.SystemTime, time); } void kusd_mmio::register_mmio() diff --git a/src/windows-emulator/syscall_utils.hpp b/src/windows-emulator/syscall_utils.hpp index e004cdea..613a09a0 100644 --- a/src/windows-emulator/syscall_utils.hpp +++ b/src/windows-emulator/syscall_utils.hpp @@ -194,80 +194,3 @@ void write_attribute(emulator& emu, const PS_ATTRIBUTE& attribute, const } } -constexpr auto HUNDRED_NANOSECONDS_IN_ONE_SECOND = 10000000LL; -constexpr auto EPOCH_DIFFERENCE_1601_TO_1970_SECONDS = 11644473600LL; -constexpr auto WINDOWS_EPOCH_DIFFERENCE = EPOCH_DIFFERENCE_1601_TO_1970_SECONDS * HUNDRED_NANOSECONDS_IN_ONE_SECOND; - -inline std::chrono::steady_clock::time_point convert_delay_interval_to_time_point(const LARGE_INTEGER delay_interval) -{ - if (delay_interval.QuadPart <= 0) - { - const auto relative_time = -delay_interval.QuadPart; - const auto relative_ticks_in_ms = relative_time / 10; - const auto relative_fraction_ns = (relative_time % 10) * 100; - const auto relative_duration = - std::chrono::microseconds(relative_ticks_in_ms) + std::chrono::nanoseconds(relative_fraction_ns); - - return std::chrono::steady_clock::now() + relative_duration; - } - - const auto delay_seconds_since_1601 = delay_interval.QuadPart / HUNDRED_NANOSECONDS_IN_ONE_SECOND; - const auto delay_fraction_ns = (delay_interval.QuadPart % HUNDRED_NANOSECONDS_IN_ONE_SECOND) * 100; - - const auto delay_seconds_since_1970 = delay_seconds_since_1601 - EPOCH_DIFFERENCE_1601_TO_1970_SECONDS; - - const auto target_time = - std::chrono::system_clock::from_time_t(delay_seconds_since_1970) + std::chrono::nanoseconds(delay_fraction_ns); - - const auto now_system = std::chrono::system_clock::now(); - - const auto duration_until_target = std::chrono::duration_cast(target_time - now_system); - - return std::chrono::steady_clock::now() + duration_until_target; -} - -inline KSYSTEM_TIME convert_to_ksystem_time(const std::chrono::system_clock::time_point& tp) -{ - const auto duration = tp.time_since_epoch(); - const auto ns_duration = std::chrono::duration_cast(duration); - - const auto total_ticks = ns_duration.count() / 100 + WINDOWS_EPOCH_DIFFERENCE; - - KSYSTEM_TIME time{}; - time.LowPart = static_cast(total_ticks); - time.High1Time = static_cast(total_ticks >> 32); - time.High2Time = time.High1Time; - - return time; -} - -inline void convert_to_ksystem_time(volatile KSYSTEM_TIME* dest, const std::chrono::system_clock::time_point& tp) -{ - const auto time = convert_to_ksystem_time(tp); - memcpy(const_cast(dest), &time, sizeof(*dest)); -} - -inline std::chrono::system_clock::time_point convert_from_ksystem_time(const KSYSTEM_TIME& time) -{ - auto totalTicks = (static_cast(time.High1Time) << 32) | time.LowPart; - totalTicks -= WINDOWS_EPOCH_DIFFERENCE; - - const auto duration = std::chrono::system_clock::duration(totalTicks * 100); - return std::chrono::system_clock::time_point(duration); -} - -inline std::chrono::system_clock::time_point convert_from_ksystem_time(const volatile KSYSTEM_TIME& time) -{ - return convert_from_ksystem_time(*const_cast(&time)); -} - -#ifndef OS_WINDOWS -using __time64_t = int64_t; -#endif - -inline LARGE_INTEGER convert_unix_to_windows_time(const __time64_t unix_time) -{ - LARGE_INTEGER windows_time{}; - windows_time.QuadPart = (unix_time + EPOCH_DIFFERENCE_1601_TO_1970_SECONDS) * HUNDRED_NANOSECONDS_IN_ONE_SECOND; - return windows_time; -} diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index 1bcb2633..48055649 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -2894,9 +2895,9 @@ namespace } file_information.access([&](FILE_BASIC_INFORMATION& info) { - info.CreationTime = convert_unix_to_windows_time(file_stat.st_atime); - info.LastAccessTime = convert_unix_to_windows_time(file_stat.st_atime); - info.LastWriteTime = convert_unix_to_windows_time(file_stat.st_mtime); + info.CreationTime = utils::convert_unix_to_windows_time(file_stat.st_atime); + info.LastAccessTime = utils::convert_unix_to_windows_time(file_stat.st_atime); + info.LastWriteTime = utils::convert_unix_to_windows_time(file_stat.st_mtime); info.ChangeTime = info.LastWriteTime; info.FileAttributes = FILE_ATTRIBUTE_NORMAL; }); @@ -3254,7 +3255,7 @@ namespace if (timeout.value() && !t.await_time.has_value()) { - t.await_time = convert_delay_interval_to_time_point(timeout.read()); + t.await_time = utils::convert_delay_interval_to_time_point(timeout.read()); } c.win_emu.yield_thread(); @@ -3281,7 +3282,7 @@ namespace if (timeout.value() && !t.await_time.has_value()) { - t.await_time = convert_delay_interval_to_time_point(timeout.read()); + t.await_time = utils::convert_delay_interval_to_time_point(timeout.read()); } c.win_emu.yield_thread(); @@ -3317,7 +3318,7 @@ namespace } auto& t = c.win_emu.current_thread(); - t.await_time = convert_delay_interval_to_time_point(delay_interval.read()); + t.await_time = utils::convert_delay_interval_to_time_point(delay_interval.read()); c.win_emu.yield_thread(); @@ -3359,7 +3360,7 @@ namespace if (timeout.value() && !t.await_time.has_value()) { - t.await_time = convert_delay_interval_to_time_point(timeout.read()); + t.await_time = utils::convert_delay_interval_to_time_point(timeout.read()); } c.win_emu.yield_thread();