Commit 3bea47883a

Linus Groh <mail@linusgroh.de>
2025-03-02 23:31:47
std.time: Make Instant.since() work on UEFI
1 parent 1a03b8c
Changed files (1)
lib
lib/std/time.zig
@@ -135,7 +135,7 @@ pub const Instant = struct {
         const clock_id = switch (builtin.os.tag) {
             .windows => {
                 // QPC on windows doesn't fail on >= XP/2000 and includes time suspended.
-                return Instant{ .timestamp = windows.QueryPerformanceCounter() };
+                return .{ .timestamp = windows.QueryPerformanceCounter() };
             },
             .wasi => {
                 var ns: std.os.wasi.timestamp_t = undefined;
@@ -147,7 +147,7 @@ pub const Instant = struct {
                 var value: std.os.uefi.Time = undefined;
                 const status = std.os.uefi.system_table.runtime_services.getTime(&value, null);
                 if (status != .success) return error.Unsupported;
-                return Instant{ .timestamp = value.toEpoch() };
+                return .{ .timestamp = value.toEpoch() };
             },
             // On darwin, use UPTIME_RAW instead of MONOTONIC as it ticks while
             // suspended.
@@ -185,36 +185,38 @@ pub const Instant = struct {
     /// This assumes that the `earlier` Instant represents a moment in time before or equal to `self`.
     /// This also assumes that the time that has passed between both Instants fits inside a u64 (~585 yrs).
     pub fn since(self: Instant, earlier: Instant) u64 {
-        if (builtin.os.tag == .windows) {
-            // We don't need to cache QPF as it's internally just a memory read to KUSER_SHARED_DATA
-            // (a read-only page of info updated and mapped by the kernel to all processes):
-            // https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/ns-ntddk-kuser_shared_data
-            // https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/api/ntexapi_x/kuser_shared_data/index.htm
-            const qpc = self.timestamp - earlier.timestamp;
-            const qpf = windows.QueryPerformanceFrequency();
-
-            // 10Mhz (1 qpc tick every 100ns) is a common enough QPF value that we can optimize on it.
-            // https://github.com/microsoft/STL/blob/785143a0c73f030238ef618890fd4d6ae2b3a3a0/stl/inc/chrono#L694-L701
-            const common_qpf = 10_000_000;
-            if (qpf == common_qpf) {
-                return qpc * (ns_per_s / common_qpf);
-            }
-
-            // Convert to ns using fixed point.
-            const scale = @as(u64, std.time.ns_per_s << 32) / @as(u32, @intCast(qpf));
-            const result = (@as(u96, qpc) * scale) >> 32;
-            return @as(u64, @truncate(result));
-        }
-
-        // WASI timestamps are directly in nanoseconds
-        if (builtin.os.tag == .wasi) {
-            return self.timestamp - earlier.timestamp;
+        switch (builtin.os.tag) {
+            .windows => {
+                // We don't need to cache QPF as it's internally just a memory read to KUSER_SHARED_DATA
+                // (a read-only page of info updated and mapped by the kernel to all processes):
+                // https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/ns-ntddk-kuser_shared_data
+                // https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/api/ntexapi_x/kuser_shared_data/index.htm
+                const qpc = self.timestamp - earlier.timestamp;
+                const qpf = windows.QueryPerformanceFrequency();
+
+                // 10Mhz (1 qpc tick every 100ns) is a common enough QPF value that we can optimize on it.
+                // https://github.com/microsoft/STL/blob/785143a0c73f030238ef618890fd4d6ae2b3a3a0/stl/inc/chrono#L694-L701
+                const common_qpf = 10_000_000;
+                if (qpf == common_qpf) {
+                    return qpc * (ns_per_s / common_qpf);
+                }
+
+                // Convert to ns using fixed point.
+                const scale = @as(u64, std.time.ns_per_s << 32) / @as(u32, @intCast(qpf));
+                const result = (@as(u96, qpc) * scale) >> 32;
+                return @as(u64, @truncate(result));
+            },
+            .uefi, .wasi => {
+                // UEFI and WASI timestamps are directly in nanoseconds
+                return self.timestamp - earlier.timestamp;
+            },
+            else => {
+                // Convert timespec diff to ns
+                const seconds = @as(u64, @intCast(self.timestamp.sec - earlier.timestamp.sec));
+                const elapsed = (seconds * ns_per_s) + @as(u32, @intCast(self.timestamp.nsec));
+                return elapsed - @as(u32, @intCast(earlier.timestamp.nsec));
+            },
         }
-
-        // Convert timespec diff to ns
-        const seconds = @as(u64, @intCast(self.timestamp.sec - earlier.timestamp.sec));
-        const elapsed = (seconds * ns_per_s) + @as(u32, @intCast(self.timestamp.nsec));
-        return elapsed - @as(u32, @intCast(earlier.timestamp.nsec));
     }
 };