Skip to content

Commit 3bea478

Browse files
committed
std.time: Make Instant.since() work on UEFI
1 parent 1a03b8c commit 3bea478

File tree

1 file changed

+33
-31
lines changed

1 file changed

+33
-31
lines changed

lib/std/time.zig

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ pub const Instant = struct {
135135
const clock_id = switch (builtin.os.tag) {
136136
.windows => {
137137
// QPC on windows doesn't fail on >= XP/2000 and includes time suspended.
138-
return Instant{ .timestamp = windows.QueryPerformanceCounter() };
138+
return .{ .timestamp = windows.QueryPerformanceCounter() };
139139
},
140140
.wasi => {
141141
var ns: std.os.wasi.timestamp_t = undefined;
@@ -147,7 +147,7 @@ pub const Instant = struct {
147147
var value: std.os.uefi.Time = undefined;
148148
const status = std.os.uefi.system_table.runtime_services.getTime(&value, null);
149149
if (status != .success) return error.Unsupported;
150-
return Instant{ .timestamp = value.toEpoch() };
150+
return .{ .timestamp = value.toEpoch() };
151151
},
152152
// On darwin, use UPTIME_RAW instead of MONOTONIC as it ticks while
153153
// suspended.
@@ -185,36 +185,38 @@ pub const Instant = struct {
185185
/// This assumes that the `earlier` Instant represents a moment in time before or equal to `self`.
186186
/// This also assumes that the time that has passed between both Instants fits inside a u64 (~585 yrs).
187187
pub fn since(self: Instant, earlier: Instant) u64 {
188-
if (builtin.os.tag == .windows) {
189-
// We don't need to cache QPF as it's internally just a memory read to KUSER_SHARED_DATA
190-
// (a read-only page of info updated and mapped by the kernel to all processes):
191-
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/ns-ntddk-kuser_shared_data
192-
// https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/api/ntexapi_x/kuser_shared_data/index.htm
193-
const qpc = self.timestamp - earlier.timestamp;
194-
const qpf = windows.QueryPerformanceFrequency();
195-
196-
// 10Mhz (1 qpc tick every 100ns) is a common enough QPF value that we can optimize on it.
197-
// https://github.com/microsoft/STL/blob/785143a0c73f030238ef618890fd4d6ae2b3a3a0/stl/inc/chrono#L694-L701
198-
const common_qpf = 10_000_000;
199-
if (qpf == common_qpf) {
200-
return qpc * (ns_per_s / common_qpf);
201-
}
202-
203-
// Convert to ns using fixed point.
204-
const scale = @as(u64, std.time.ns_per_s << 32) / @as(u32, @intCast(qpf));
205-
const result = (@as(u96, qpc) * scale) >> 32;
206-
return @as(u64, @truncate(result));
207-
}
208-
209-
// WASI timestamps are directly in nanoseconds
210-
if (builtin.os.tag == .wasi) {
211-
return self.timestamp - earlier.timestamp;
188+
switch (builtin.os.tag) {
189+
.windows => {
190+
// We don't need to cache QPF as it's internally just a memory read to KUSER_SHARED_DATA
191+
// (a read-only page of info updated and mapped by the kernel to all processes):
192+
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/ns-ntddk-kuser_shared_data
193+
// https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/api/ntexapi_x/kuser_shared_data/index.htm
194+
const qpc = self.timestamp - earlier.timestamp;
195+
const qpf = windows.QueryPerformanceFrequency();
196+
197+
// 10Mhz (1 qpc tick every 100ns) is a common enough QPF value that we can optimize on it.
198+
// https://github.com/microsoft/STL/blob/785143a0c73f030238ef618890fd4d6ae2b3a3a0/stl/inc/chrono#L694-L701
199+
const common_qpf = 10_000_000;
200+
if (qpf == common_qpf) {
201+
return qpc * (ns_per_s / common_qpf);
202+
}
203+
204+
// Convert to ns using fixed point.
205+
const scale = @as(u64, std.time.ns_per_s << 32) / @as(u32, @intCast(qpf));
206+
const result = (@as(u96, qpc) * scale) >> 32;
207+
return @as(u64, @truncate(result));
208+
},
209+
.uefi, .wasi => {
210+
// UEFI and WASI timestamps are directly in nanoseconds
211+
return self.timestamp - earlier.timestamp;
212+
},
213+
else => {
214+
// Convert timespec diff to ns
215+
const seconds = @as(u64, @intCast(self.timestamp.sec - earlier.timestamp.sec));
216+
const elapsed = (seconds * ns_per_s) + @as(u32, @intCast(self.timestamp.nsec));
217+
return elapsed - @as(u32, @intCast(earlier.timestamp.nsec));
218+
},
212219
}
213-
214-
// Convert timespec diff to ns
215-
const seconds = @as(u64, @intCast(self.timestamp.sec - earlier.timestamp.sec));
216-
const elapsed = (seconds * ns_per_s) + @as(u32, @intCast(self.timestamp.nsec));
217-
return elapsed - @as(u32, @intCast(earlier.timestamp.nsec));
218220
}
219221
};
220222

0 commit comments

Comments
 (0)