Commit bffbc918ee

Ali Cheraghi <alichraghi@proton.me>
2025-02-12 15:26:37
std.time: more precise `nanoTimestamp` in windows
1 parent d12123a
Changed files (4)
lib/std/os/windows/kernel32.zig
@@ -656,9 +656,4 @@ pub extern "kernel32" fn SetLastError(
 
 // Everything Else
 
-// TODO:
-//  Wrapper around KUSER_SHARED_DATA.SystemTime.
-//  Much better to use NtQuerySystemTime or NtQuerySystemTimePrecise for guaranteed 0.1ns precision.
-pub extern "kernel32" fn GetSystemTimeAsFileTime(lpSystemTimeAsFileTime: *FILETIME) callconv(.winapi) void;
-
 pub extern "kernel32" fn GetSystemInfo(lpSystemInfo: *SYSTEM_INFO) callconv(.winapi) void;
lib/std/os/windows/ntdll.zig
@@ -92,6 +92,7 @@ pub extern "ntdll" fn RtlVirtualUnwind(
     EstablisherFrame: *DWORD64,
     ContextPointers: ?*KNONVOLATILE_CONTEXT_POINTERS,
 ) callconv(.winapi) *EXCEPTION_ROUTINE;
+pub extern "ntdll" fn RtlGetSystemTimePrecise() callconv(.winapi) LARGE_INTEGER;
 pub extern "ntdll" fn NtQueryInformationFile(
     FileHandle: HANDLE,
     IoStatusBlock: *IO_STATUS_BLOCK,
lib/std/posix.zig
@@ -5693,7 +5693,10 @@ pub const ClockGetTimeError = error{UnsupportedClock} || UnexpectedError;
 
 pub fn clock_gettime(clock_id: clockid_t) ClockGetTimeError!timespec {
     var tp: timespec = undefined;
-    if (native_os == .wasi and !builtin.link_libc) {
+
+    if (native_os == .windows) {
+        @compileError("Windows does not support POSIX; use Windows-specific API or cross-platform std.time API");
+    } else if (native_os == .wasi and !builtin.link_libc) {
         var ts: timestamp_t = undefined;
         switch (system.clock_time_get(clock_id, 1, &ts)) {
             .SUCCESS => {
@@ -5707,23 +5710,6 @@ pub fn clock_gettime(clock_id: clockid_t) ClockGetTimeError!timespec {
         }
         return tp;
     }
-    if (native_os == .windows) {
-        if (clock_id == .REALTIME) {
-            var ft: windows.FILETIME = undefined;
-            windows.kernel32.GetSystemTimeAsFileTime(&ft);
-            // FileTime has a granularity of 100 nanoseconds and uses the NTFS/Windows epoch.
-            const ft64 = (@as(u64, ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
-            const ft_per_s = std.time.ns_per_s / 100;
-            tp = .{
-                .sec = @as(i64, @intCast(ft64 / ft_per_s)) + std.time.epoch.windows,
-                .nsec = @as(c_long, @intCast(ft64 % ft_per_s)) * 100,
-            };
-            return tp;
-        } else {
-            // TODO POSIX implementation of CLOCK.MONOTONIC on Windows.
-            return error.UnsupportedClock;
-        }
-    }
 
     switch (errno(system.clock_gettime(clock_id, &tp))) {
         .SUCCESS => return tp,
lib/std/time.zig
@@ -47,13 +47,10 @@ pub fn microTimestamp() i64 {
 pub fn nanoTimestamp() i128 {
     switch (builtin.os.tag) {
         .windows => {
-            // FileTime has a granularity of 100 nanoseconds and uses the NTFS/Windows epoch,
+            // RtlGetSystemTimePrecise() has a granularity of 100 nanoseconds and uses the NTFS/Windows epoch,
             // which is 1601-01-01.
             const epoch_adj = epoch.windows * (ns_per_s / 100);
-            var ft: windows.FILETIME = undefined;
-            windows.kernel32.GetSystemTimeAsFileTime(&ft);
-            const ft64 = (@as(u64, ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
-            return @as(i128, @as(i64, @bitCast(ft64)) + epoch_adj) * 100;
+            return @as(i128, windows.ntdll.RtlGetSystemTimePrecise() + epoch_adj) * 100;
         },
         .wasi => {
             var ns: std.os.wasi.timestamp_t = undefined;