mirror of
https://github.com/rdmsr/zag.git
synced 2026-11-01 23:58:21 +00:00
all: type-safe time units
This commit is contained in:
+2
-2
@@ -113,7 +113,7 @@ fn dispatch_queue(cpu: u32) void {
|
||||
if (sched_cpu.start_timer) {
|
||||
ke.timer.set(
|
||||
&sched_cpu.resched_timer,
|
||||
std.time.ns_per_ms * config.sched_timeslice,
|
||||
.from(r.Milliseconds.init(config.sched_timeslice)),
|
||||
.{ .dpc = &sched_cpu.resched_dpc },
|
||||
);
|
||||
}
|
||||
@@ -123,7 +123,7 @@ fn dispatch_queue(cpu: u32) void {
|
||||
ke.timer.cancel(&sched_cpu.resched_timer);
|
||||
ke.timer.set(
|
||||
&sched_cpu.resched_timer,
|
||||
std.time.ns_per_ms * config.sched_timeslice,
|
||||
.from(r.Milliseconds.init(config.sched_timeslice)),
|
||||
.{ .dpc = &sched_cpu.resched_dpc },
|
||||
);
|
||||
}
|
||||
|
||||
+7
-1
@@ -20,7 +20,13 @@ pub fn init(boot_info: *r.BootInfo) linksection(r.init) void {
|
||||
ki.cpu.init_cpu(0);
|
||||
ki.turnstile.init_turnstiles();
|
||||
|
||||
thread0.init(@intFromPtr(&stack), r.kib(16), ke.Thread.Priority.idle_low, ki.sched.idle, null);
|
||||
thread0.init(
|
||||
@intFromPtr(&stack),
|
||||
r.kib(16),
|
||||
ke.Thread.Priority.idle_low,
|
||||
ki.sched.idle,
|
||||
null,
|
||||
);
|
||||
thread0.priority = 0;
|
||||
thread0.base_priority = 0;
|
||||
thread0.pinned = true;
|
||||
|
||||
+7
-1
@@ -89,6 +89,12 @@ pub fn log(
|
||||
const ipl = out_lock.acquire_at(.High);
|
||||
defer out_lock.release(ipl);
|
||||
|
||||
writer.interface.print("[{:>5}.{:06}] ", .{ res.info.timestamp / std.time.ns_per_s, (res.info.timestamp % std.time.ns_per_s) / std.time.ns_per_us }) catch return;
|
||||
writer.interface.print(
|
||||
"[{:>5}.{:06}] ",
|
||||
.{
|
||||
res.info.timestamp.value / std.time.ns_per_s,
|
||||
(res.info.timestamp.value % std.time.ns_per_s) / std.time.ns_per_us,
|
||||
},
|
||||
) catch return;
|
||||
_ = writer.interface.writeAll(res.buf[0..res.info.length]) catch return;
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ const Desc = struct {
|
||||
|
||||
pub const Info = struct {
|
||||
sequence: u64,
|
||||
timestamp: u64,
|
||||
timestamp: r.Nanoseconds,
|
||||
length: u16,
|
||||
};
|
||||
|
||||
|
||||
+10
-10
@@ -215,7 +215,7 @@ pub const Average = struct {
|
||||
// Amount of the period that has been accounted for
|
||||
period_contrib: usize,
|
||||
/// Timestamp (us) up to which history has been accounted.
|
||||
last_update: u64,
|
||||
last_update: r.Microseconds,
|
||||
};
|
||||
|
||||
pub const percpu = ke.CpuLocal(PerCpu, undefined);
|
||||
@@ -242,8 +242,8 @@ fn pelt_do_decay(val: u64, n: u64) u64 {
|
||||
}
|
||||
|
||||
fn pelt_update(avg: *Average, runnable: bool) void {
|
||||
const now = ke.time.read_time() / std.time.ns_per_us;
|
||||
const new_delta = now - avg.last_update;
|
||||
const now = ke.time.read_time().to(r.Microseconds);
|
||||
const new_delta = now.value - avg.last_update.value;
|
||||
|
||||
if (new_delta == 0) return;
|
||||
|
||||
@@ -318,8 +318,8 @@ fn pelt_update_td(td: *ke.Thread, cpu: ?*PerCpu, runnable: bool) void {
|
||||
fn attach_load_avg(cpu: *PerCpu, td: *ke.Thread) void {
|
||||
if (!tracks_load_avg(td)) return;
|
||||
|
||||
if (td.avg.last_update == 0) {
|
||||
td.avg.last_update = ke.time.read_time() / std.time.ns_per_us;
|
||||
if (td.avg.last_update.value == 0) {
|
||||
td.avg.last_update = ke.time.read_time().to(r.Microseconds);
|
||||
} else {
|
||||
pelt_update_td(td, null, false);
|
||||
}
|
||||
@@ -470,7 +470,7 @@ pub fn block() void {
|
||||
/// Block the currently running thread with its lock held.
|
||||
pub fn block_locked(curtd: *ke.Thread) void {
|
||||
curtd.state.store(.Blocked, .monotonic);
|
||||
curtd.sleep_start = ke.time.read_time();
|
||||
curtd.sleep_start = ke.time.read_time().value;
|
||||
curtd.runq = null;
|
||||
|
||||
detach_load_avg(percpu.local(), curtd);
|
||||
@@ -537,7 +537,7 @@ pub fn unblock_locked(td: *ke.Thread) void {
|
||||
std.debug.assert(td.lock.is_locked());
|
||||
std.debug.assert(td.state.load(.monotonic) == .Blocked);
|
||||
|
||||
const delta = (ke.time.read_time() - td.sleep_start) / std.time.ns_per_ms;
|
||||
const delta = (ke.time.read_time().value - td.sleep_start) / std.time.ns_per_ms;
|
||||
|
||||
td.sleep_time += delta;
|
||||
|
||||
@@ -685,7 +685,7 @@ pub fn late_init() linksection(r.init) void {
|
||||
balance_timer.init();
|
||||
ke.timer.set(
|
||||
&balance_timer,
|
||||
balance_interval * std.time.ns_per_ms,
|
||||
.from(r.Milliseconds.init(balance_interval)),
|
||||
.{ .dpc = &balance_dpc },
|
||||
);
|
||||
}
|
||||
@@ -1136,7 +1136,7 @@ fn pick_cpu(td: *ke.Thread) u32 {
|
||||
var ran_recently = true;
|
||||
|
||||
if (td.sleep_start != 0) {
|
||||
const delta = ke.time.read_time() - td.sleep_start;
|
||||
const delta = ke.time.read_time().value - td.sleep_start;
|
||||
|
||||
// If we haven't been on this CPU in the last second, don't bother.
|
||||
if (delta > std.time.ns_per_s) {
|
||||
@@ -1455,5 +1455,5 @@ fn balance(_: *ke.Dpc, _: ?*anyopaque) void {
|
||||
const offset = lcg.next() % balance_interval;
|
||||
const ms = (balance_interval) + offset;
|
||||
|
||||
ke.timer.set(&balance_timer, ms * std.time.ns_per_ms, .{ .dpc = &balance_dpc });
|
||||
ke.timer.set(&balance_timer, .from(r.Milliseconds.init(ms)), .{ .dpc = &balance_dpc });
|
||||
}
|
||||
|
||||
+1
-1
@@ -159,7 +159,7 @@ pub const Thread = struct {
|
||||
.stack = stack,
|
||||
.switching = .init(false),
|
||||
.avg = .{
|
||||
.last_update = 0,
|
||||
.last_update = .init(0),
|
||||
// New threads are considered heavy until they prove themselves,
|
||||
// this might allow for better balancing during bursts.
|
||||
.load = ki.sched.pelt_load_avg_max,
|
||||
|
||||
+5
-5
@@ -89,12 +89,12 @@ pub fn register_source(tc: *TimeCounter) void {
|
||||
|
||||
/// Return the time elapsed since boot in nanoseconds.
|
||||
pub fn read_time() r.Nanoseconds {
|
||||
const tc = best_tc orelse return 0;
|
||||
const tc = best_tc orelse return .init(0);
|
||||
|
||||
const s = state.load();
|
||||
const curr_count = tc.read_count() & tc.mask;
|
||||
const elapsed = (curr_count - s.initial_count) & tc.mask;
|
||||
return s.offset + ticks_to_ns(tc, elapsed);
|
||||
return .init(s.offset + ticks_to_ns(tc, elapsed));
|
||||
}
|
||||
|
||||
/// Return the best TimeCounter.
|
||||
@@ -109,14 +109,14 @@ pub fn sleep(ns: r.Nanoseconds) void {
|
||||
while (true) {
|
||||
var cur = read_time();
|
||||
|
||||
if (cur < start) continue;
|
||||
if (cur.value < start.value) continue;
|
||||
|
||||
if (cur - start >= ns) {
|
||||
if (cur.value - start.value >= ns.value) {
|
||||
cur = read_time();
|
||||
|
||||
// Check again as we may have overflowed and read a bogus value..
|
||||
// This is kinda hacky but oh well.
|
||||
if (cur - start >= ns) {
|
||||
if (cur.value - start.value >= ns.value) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+7
-7
@@ -42,7 +42,7 @@ pub const Timer = struct {
|
||||
self.* = .{
|
||||
.hdr = undefined,
|
||||
.state = .init(.Stopped),
|
||||
.deadline = 0,
|
||||
.deadline = .init(0),
|
||||
.dpc = null,
|
||||
.node = .{},
|
||||
.cpu = null,
|
||||
@@ -79,7 +79,7 @@ pub fn set(timer: *Timer, time: r.Nanoseconds, opts: Options) void {
|
||||
defer cpu.lock.release_no_ipl();
|
||||
|
||||
// Initialize the timer.
|
||||
timer.deadline = ke.time.read_time() + time;
|
||||
timer.deadline = .init(ke.time.read_time().value + time.value);
|
||||
|
||||
timer.cpu = cpu;
|
||||
timer.dpc = opts.dpc;
|
||||
@@ -130,7 +130,7 @@ pub fn cmp_timer(a: *rtl.pairing_heap.Node, b_: *rtl.pairing_heap.Node) std.math
|
||||
const timer_a: *Timer = @fieldParentPtr("node", a);
|
||||
const timer_b: *Timer = @fieldParentPtr("node", b_);
|
||||
|
||||
return std.math.order(timer_a.deadline, timer_b.deadline);
|
||||
return std.math.order(timer_a.deadline.value, timer_b.deadline.value);
|
||||
}
|
||||
|
||||
/// Called by the platform on a clock interrupt.
|
||||
@@ -161,18 +161,18 @@ fn handle_expiry(_: *ke.Dpc, _: ?*anyopaque) void {
|
||||
|
||||
// If the timer expires more than 1ms in the future, consider it not yet due.
|
||||
// Sub-millisecond differences are close enough to expire immediately.
|
||||
if (timer.deadline > curtime and timer.deadline - curtime > std.time.ns_per_ms) {
|
||||
if (timer.deadline.value > curtime.value and timer.deadline.value - curtime.value > std.time.ns_per_ms) {
|
||||
const next = timer;
|
||||
cpu.lock.release_no_ipl();
|
||||
|
||||
// Re-check in case the timer expired while we were here.
|
||||
const now = ke.time.read_time();
|
||||
if (next.deadline <= now or next.deadline - now <= std.time.ns_per_ms) {
|
||||
if (next.deadline.value <= now.value or next.deadline.value - now.value <= std.time.ns_per_ms) {
|
||||
continue; // expired in the meantime, loop again
|
||||
}
|
||||
|
||||
std.debug.assert(next.deadline > now);
|
||||
pl.arm_timer(next.deadline - now);
|
||||
std.debug.assert(next.deadline.value > now.value);
|
||||
pl.arm_timer(.init(next.deadline.value - now.value));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -166,7 +166,7 @@ pub fn wait_any(objects: []*DispatchHeader, reason: []const u8, opts: Options) !
|
||||
}
|
||||
|
||||
// Wait was already satisfied, back out.
|
||||
if (satisfier != null or (has_timeout and opts.timeout.? == 0)) {
|
||||
if (satisfier != null or (has_timeout and opts.timeout.?.value == 0)) {
|
||||
if (satisfier != null) {
|
||||
std.debug.assert(curtd.wait_status.load(.acquire) == .Satisfied);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user