From 0c3e48507dc5f6424d5b10b6e230046a4c2095cd Mon Sep 17 00:00:00 2001 From: Evan Martin <evan.martin@gmail.com> Date: Fri, 20 Sep 2024 09:29:04 -0700 Subject: [PATCH] a few time fixes 1) Rename ticks() (arbitrary millisecond counter) to make it clearly distinct from system time. 2) msvcrt's time() gets unix time which is fed to srand so it needs system time, not ticks. 3) time64 returns 64-bit time_t which normally goes through edx:eax, but the shims machinery is not set up for this so we truncate at y2k38. --- cli/src/host.rs | 2 +- web/glue/src/host.rs | 2 +- win32/src/host.rs | 3 ++- win32/src/winapi/kernel32/time.rs | 6 +++--- win32/src/winapi/ucrtbase.rs | 31 ++++++++++++------------------ win32/src/winapi/user32/message.rs | 2 +- win32/src/winapi/user32/timer.rs | 4 ++-- win32/src/winapi/winmm/time.rs | 2 +- 8 files changed, 23 insertions(+), 29 deletions(-) diff --git a/cli/src/host.rs b/cli/src/host.rs index fe35d854..41f18aeb 100644 --- a/cli/src/host.rs +++ b/cli/src/host.rs @@ -123,7 +123,7 @@ impl win32::Host for EnvRef { self.0.borrow_mut().exit_code = Some(code); } - fn time(&self) -> u32 { + fn ticks(&self) -> u32 { let mut env = self.0.borrow_mut(); let gui = env.ensure_gui().unwrap(); gui.time() diff --git a/web/glue/src/host.rs b/web/glue/src/host.rs index fc84ed46..8bb437d5 100644 --- a/web/glue/src/host.rs +++ b/web/glue/src/host.rs @@ -283,7 +283,7 @@ impl win32::Host for JsHost { JsHost::exit(self, exit_code) } - fn time(&self) -> u32 { + fn ticks(&self) -> u32 { web_sys::window().unwrap().performance().unwrap().now() as u32 } diff --git a/win32/src/host.rs b/win32/src/host.rs index a5de8cc3..a1d9d1c3 100644 --- a/win32/src/host.rs +++ b/win32/src/host.rs @@ -127,7 +127,8 @@ pub struct Message { pub trait Host { fn exit(&self, code: u32); - fn time(&self) -> u32; + /// Get an arbitrary time counter, measured in milliseconds. + fn ticks(&self) -> u32; fn system_time(&self) -> chrono::DateTime<chrono::Local>; /// Get the next pending message, or None if no message waiting. diff --git a/win32/src/winapi/kernel32/time.rs b/win32/src/winapi/kernel32/time.rs index 4742fb58..0627c0c5 100644 --- a/win32/src/winapi/kernel32/time.rs +++ b/win32/src/winapi/kernel32/time.rs @@ -8,7 +8,7 @@ const TRACE_CONTEXT: &'static str = "kernel32/time"; #[win32_derive::dllexport] pub fn GetTickCount(machine: &mut Machine) -> u32 { - machine.host.time() + machine.host.ticks() } // The number of "counts" per second, where counts are the units returned by @@ -33,7 +33,7 @@ pub fn QueryPerformanceCounter( lpPerformanceCount: Option<&mut LARGE_INTEGER>, ) -> bool { let counter = lpPerformanceCount.unwrap(); - let ms = machine.host.time(); + let ms = machine.host.ticks(); let counts = ms as u64 * (QUERY_PERFORMANCE_FREQ as u64 / 1000); counter.LowPart = counts as u32; counter.HighPart = (counts >> 32) as u32 as i32; @@ -154,7 +154,7 @@ pub async fn Sleep(machine: &mut Machine, dwMilliseconds: u32) -> u32 { #[cfg(feature = "x86-emu")] { - let until = machine.host.time() + dwMilliseconds; + let until = machine.host.ticks() + dwMilliseconds; machine.emu.x86.cpu_mut().block(Some(until)).await; } diff --git a/win32/src/winapi/ucrtbase.rs b/win32/src/winapi/ucrtbase.rs index 9613c0d9..7b4d2d72 100644 --- a/win32/src/winapi/ucrtbase.rs +++ b/win32/src/winapi/ucrtbase.rs @@ -179,7 +179,8 @@ pub fn free(machine: &mut Machine, ptr: u32) -> u32 { 0 } -static mut RAND_STATE: u32 = 0; +// MSDN: "Calling rand before any call to srand generates the same sequence as calling srand with seed passed as 1." +static mut RAND_STATE: u32 = 1; #[win32_derive::dllexport(cdecl)] pub fn srand(machine: &mut Machine, seed: u32) { @@ -197,32 +198,24 @@ pub fn rand(machine: &mut Machine) -> u32 { } } -fn time64(machine: &mut Machine, destTime: Option<&mut u64>) -> u64 { - let time = machine.host.time() as u64 / 1000; +fn time64(machine: &mut Machine, destTime: Option<&mut u64>) -> u32 { + let time = machine.host.system_time().timestamp() as u64; if let Some(destTime) = destTime { *destTime = time; } - // TODO: need to figure out 64-bit return values in general. - // It appears to go through edx:eax. - - #[cfg(feature = "x86-emu")] - { - x86::set_edx_eax(machine.emu.x86.cpu_mut(), time); - time - } - #[cfg(not(feature = "x86-emu"))] - { - unimplemented!(); - } + // TODO: 64-bit return values go through edx:eax, which is not yet modeled in the shims + // machinery, so we only return 32 bits here. + // Thankfully 32-bit time_t only overflows in 2038 anyway. + time as u32 } #[win32_derive::dllexport(cdecl)] -pub fn time(machine: &mut Machine, destTime: Option<&mut u64>) { - time64(machine, destTime); +pub fn time(machine: &mut Machine, destTime: Option<&mut u64>) -> u32 { + time64(machine, destTime) } #[win32_derive::dllexport(cdecl)] -pub fn _time64(machine: &mut Machine, destTime: Option<&mut u64>) { - time64(machine, destTime); +pub fn _time64(machine: &mut Machine, destTime: Option<&mut u64>) -> u32 { + time64(machine, destTime) } diff --git a/win32/src/winapi/user32/message.rs b/win32/src/winapi/user32/message.rs index 8591c6ca..cc64b49a 100644 --- a/win32/src/winapi/user32/message.rs +++ b/win32/src/winapi/user32/message.rs @@ -104,7 +104,7 @@ fn enqueue_timer_event_if_ready(machine: &mut Machine, hwnd: HWND) -> Result<(), return Err(None); } - let now = machine.host.time(); + let now = machine.host.ticks(); if let Some(timer) = machine.state.user32.timers.find_next(hwnd, now) { machine .state diff --git a/win32/src/winapi/user32/timer.rs b/win32/src/winapi/user32/timer.rs index e847cb1d..98b1a6ad 100644 --- a/win32/src/winapi/user32/timer.rs +++ b/win32/src/winapi/user32/timer.rs @@ -80,7 +80,7 @@ pub fn SetTimer( { Some(timer) => { timer.period = uElapse; - timer.next = machine.host.time() + uElapse; + timer.next = machine.host.ticks() + uElapse; timer.func = lpTimerFunc; timer.id } @@ -90,7 +90,7 @@ pub fn SetTimer( id, hwnd: hWnd, period: uElapse, - next: machine.host.time() + uElapse, + next: machine.host.ticks() + uElapse, func: lpTimerFunc, }; machine.state.user32.timers.0.push(timer); diff --git a/win32/src/winapi/winmm/time.rs b/win32/src/winapi/winmm/time.rs index ffedf5d7..46b2cd17 100644 --- a/win32/src/winapi/winmm/time.rs +++ b/win32/src/winapi/winmm/time.rs @@ -16,7 +16,7 @@ pub fn timeSetEvent( #[win32_derive::dllexport] pub fn timeGetTime(machine: &mut Machine) -> u32 { - machine.host.time() + machine.host.ticks() } const TIMERR_NOERROR: u32 = 0;