Fix the drviers typo and make tests robust to source-path debug prefixes

The debug-message refactor prefixed each service/driver line with its
source path (system/drivers/hpet:, ...) for readability, but two things
left main red: a 'drviers' typo in hpet.zig and pci-bus.zig, and five
kernel tests (init, hpet, pci-scan, device-manager, vfs-client-death)
that starts-with-matched the old short markers, which no longer sit at
the front of the prefixed lines.

Fix the typo, and convert the fragile starts-with matchers to substring
matching via a bufferHas helper — 'hpet: ok' now matches inside
'system/drivers/hpet: ok' regardless of prefix. Future-proof against
further prefix changes and harmless for the tests that already passed.
Suite 58/58.
This commit is contained in:
Daniel Samson
2026-07-13 06:23:21 +01:00
parent dd044fb115
commit 6e60daed6a
3 changed files with 60 additions and 55 deletions
+11 -11
View File
@@ -93,21 +93,21 @@ fn findHpet(buffer: []device.DeviceDescriptor) ?Found {
pub fn main() void { pub fn main() void {
// Enumerate into a heap buffer (too big for the one-page user stack). // Enumerate into a heap buffer (too big for the one-page user stack).
const buffer = runtime.allocator().alloc(device.DeviceDescriptor, 32) catch { const buffer = runtime.allocator().alloc(device.DeviceDescriptor, 32) catch {
_ = runtime.system.write("system/drviers/hpet: out of memory\n"); _ = runtime.system.write("system/drivers/hpet: out of memory\n");
return; return;
}; };
const hpet = findHpet(buffer) orelse { const hpet = findHpet(buffer) orelse {
_ = runtime.system.write("system/drviers/hpet: no HPET with an IRQ\n"); _ = runtime.system.write("system/drivers/hpet: no HPET with an IRQ\n");
return; return;
}; };
if (!device.claim(hpet.device_id)) { if (!device.claim(hpet.device_id)) {
_ = runtime.system.write("system/drviers/hpet: claim failed\n"); _ = runtime.system.write("system/drivers/hpet: claim failed\n");
return; return;
} }
const base = device.mmioMap(hpet.device_id, hpet.mmio) orelse { const base = device.mmioMap(hpet.device_id, hpet.mmio) orelse {
_ = runtime.system.write("system/drviers/hpet: mmio_map failed\n"); _ = runtime.system.write("system/drivers/hpet: mmio_map failed\n");
return; return;
}; };
@@ -116,7 +116,7 @@ pub fn main() void {
const gsi = hpet.gsi; const gsi = hpet.gsi;
const endpoint = ipc.createIpcEndpoint() orelse { const endpoint = ipc.createIpcEndpoint() orelse {
_ = runtime.system.write("system/drviers/hpet: create_ipc_endpoint failed\n"); _ = runtime.system.write("system/drivers/hpet: create_ipc_endpoint failed\n");
return; return;
}; };
@@ -124,7 +124,7 @@ pub fn main() void {
// Counter period, so we can arm the comparator a fixed wall-clock distance out. // Counter period, so we can arm the comparator a fixed wall-clock distance out.
const femtos_per_tick = rd(base, register_general_cap) >> 32; const femtos_per_tick = rd(base, register_general_cap) >> 32;
if (femtos_per_tick == 0) { if (femtos_per_tick == 0) {
_ = runtime.system.write("system/drviers/hpet: bad HPET period\n"); _ = runtime.system.write("system/drivers/hpet: bad HPET period\n");
return; return;
} }
const ticks_per_ms = 1_000_000_000_000 / femtos_per_tick; const ticks_per_ms = 1_000_000_000_000 / femtos_per_tick;
@@ -147,10 +147,10 @@ pub fn main() void {
wr(base, register_general_configuration, rd(base, register_general_configuration) | configuration_enable); wr(base, register_general_configuration, rd(base, register_general_configuration) | configuration_enable);
if (!device.irqBind(hpet.device_id, hpet.irq, endpoint)) { if (!device.irqBind(hpet.device_id, hpet.irq, endpoint)) {
_ = runtime.system.write("system/drviers/hpet: irq_bind failed\n"); _ = runtime.system.write("system/drivers/hpet: irq_bind failed\n");
return; return;
} }
_ = runtime.system.write("system/drviers/hpet: bound, sleeping until the hardware speaks\n"); _ = runtime.system.write("system/drivers/hpet: bound, sleeping until the hardware speaks\n");
// --- the driver loop ----------------------------------------------------- // --- the driver loop -----------------------------------------------------
// Blocked in replyWait. No polling, no spinning: the next line of this function // Blocked in replyWait. No polling, no spinning: the next line of this function
@@ -178,14 +178,14 @@ pub fn main() void {
wr(base, register_timer0_configuration, rd(base, register_timer0_configuration) & ~tn_int_enb); wr(base, register_timer0_configuration, rd(base, register_timer0_configuration) & ~tn_int_enb);
} }
_ = runtime.system.write("system/drviers/hpet: irq\n"); _ = runtime.system.write("system/drivers/hpet: irq\n");
if (!device.irqAck(hpet.device_id, hpet.irq)) { if (!device.irqAck(hpet.device_id, hpet.irq)) {
_ = runtime.system.write("system/drviers/hpet: irq_ack failed\n"); _ = runtime.system.write("system/drivers/hpet: irq_ack failed\n");
return; return;
} }
} }
_ = runtime.system.write("system/drviers/hpet: ok\n"); _ = runtime.system.write("system/drivers/hpet: ok\n");
while (true) runtime.system.sleep(1000); while (true) runtime.system.sleep(1000);
} }
+16 -16
View File
@@ -6,7 +6,7 @@
//! M19.1 (this increment): claim the bridge, map its ECAM window (resource 0; //! M19.1 (this increment): claim the bridge, map its ECAM window (resource 0;
//! the bus range and the MMIO apertures follow it), walk every //! the bus range and the MMIO apertures follow it), walk every
//! bus/device/function config header, and log what the walk finds — ending //! bus/device/function config header, and log what the walk finds — ending
//! with "/system/drviers/pci-bus: N functions found", which the `pci-scan` scenario compares //! with "/system/drivers/pci-bus: N functions found", which the `pci-scan` scenario compares
//! against the kernel's own enumeration. Registration and reports (M19.2), and //! against the kernel's own enumeration. Registration and reports (M19.2), and
//! the kernel walk's retirement (M19.3), build on this proven-equivalent scan. //! the kernel walk's retirement (M19.3), build on this proven-equivalent scan.
@@ -31,9 +31,9 @@ fn logFunction(bus: u64, dev: u64, function: u64, class_triple: u32) void {
const pif = pci_class.progIfName(cc.base, cc.subclass, cc.prog_if); const pif = pci_class.progIfName(cc.base, cc.subclass, cc.prog_if);
var line: [200]u8 = undefined; var line: [200]u8 = undefined;
const text = if (pif.len != 0) const text = if (pif.len != 0)
std.fmt.bufPrint(&line, "/system/drviers/pci-bus: {d}:{d}.{d} class 0x{x:0>2} ({s}) subclass 0x{x:0>2} ({s}) progif 0x{x:0>2} ({s})\n", .{ bus, dev, function, cc.base, pci_class.className(cc.base), cc.subclass, pci_class.subclassName(cc.base, cc.subclass), cc.prog_if, pif }) catch return std.fmt.bufPrint(&line, "/system/drivers/pci-bus: {d}:{d}.{d} class 0x{x:0>2} ({s}) subclass 0x{x:0>2} ({s}) progif 0x{x:0>2} ({s})\n", .{ bus, dev, function, cc.base, pci_class.className(cc.base), cc.subclass, pci_class.subclassName(cc.base, cc.subclass), cc.prog_if, pif }) catch return
else else
std.fmt.bufPrint(&line, "/system/drviers/pci-bus: {d}:{d}.{d} class 0x{x:0>2} ({s}) subclass 0x{x:0>2} ({s}) progif 0x{x:0>2}\n", .{ bus, dev, function, cc.base, pci_class.className(cc.base), cc.subclass, pci_class.subclassName(cc.base, cc.subclass), cc.prog_if }) catch return; std.fmt.bufPrint(&line, "/system/drivers/pci-bus: {d}:{d}.{d} class 0x{x:0>2} ({s}) subclass 0x{x:0>2} ({s}) progif 0x{x:0>2}\n", .{ bus, dev, function, cc.base, pci_class.className(cc.base), cc.subclass, pci_class.subclassName(cc.base, cc.subclass), cc.prog_if }) catch return;
_ = runtime.system.write(text); _ = runtime.system.write(text);
} }
@@ -74,37 +74,37 @@ fn configWrite16(bus: u64, dev: u64, function: u64, offset: u64, value: u16) voi
fn initialise(endpoint: runtime.ipc.Handle) bool { fn initialise(endpoint: runtime.ipc.Handle) bool {
_ = endpoint; _ = endpoint;
if (!device.claim(bridge_id)) { if (!device.claim(bridge_id)) {
writeLine("/system/drviers/pci-bus: unable to claim bridge device {d}\n", .{bridge_id}); writeLine("/system/drivers/pci-bus: unable to claim bridge device {d}\n", .{bridge_id});
return false; return false;
} }
const buffer = runtime.allocator().alloc(device.DeviceDescriptor, 64) catch { const buffer = runtime.allocator().alloc(device.DeviceDescriptor, 64) catch {
_ = runtime.system.write("/system/drviers/pci-bus: out of memory\n"); _ = runtime.system.write("/system/drivers/pci-bus: out of memory\n");
return false; return false;
}; };
const total = device.enumerate(buffer); const total = device.enumerate(buffer);
const descriptor = for (buffer[0..@min(total, buffer.len)]) |d| { const descriptor = for (buffer[0..@min(total, buffer.len)]) |d| {
if (d.id == bridge_id) break d; if (d.id == bridge_id) break d;
} else { } else {
writeLine("/system/drviers/pci-bus: device {d} not in the device tree\n", .{bridge_id}); writeLine("/system/drivers/pci-bus: device {d} not in the device tree\n", .{bridge_id});
return false; return false;
}; };
// Resource 0 is the ECAM window (1 MiB of config space per bus); the bus // Resource 0 is the ECAM window (1 MiB of config space per bus); the bus
// range rides beside it. The MMIO apertures (M19.0) come after both. // range rides beside it. The MMIO apertures (M19.0) come after both.
if (descriptor.resource_count < 2 or descriptor.resources[0].kind != @intFromEnum(device.ResourceKind.memory)) { if (descriptor.resource_count < 2 or descriptor.resources[0].kind != @intFromEnum(device.ResourceKind.memory)) {
_ = runtime.system.write("/system/drviers/pci-bus: bridge has no ECAM window\n"); _ = runtime.system.write("/system/drivers/pci-bus: bridge has no ECAM window\n");
return false; return false;
} }
const bus_range = for (descriptor.resources[0..@intCast(descriptor.resource_count)]) |resource| { const bus_range = for (descriptor.resources[0..@intCast(descriptor.resource_count)]) |resource| {
if (resource.kind == @intFromEnum(device.ResourceKind.bus_range)) break resource; if (resource.kind == @intFromEnum(device.ResourceKind.bus_range)) break resource;
} else { } else {
_ = runtime.system.write("/system/drviers/pci-bus: bridge has no bus range\n"); _ = runtime.system.write("/system/drivers/pci-bus: bridge has no bus range\n");
return false; return false;
}; };
start_bus = bus_range.start; start_bus = bus_range.start;
bus_count = bus_range.len; bus_count = bus_range.len;
ecam_physical = descriptor.resources[0].start; ecam_physical = descriptor.resources[0].start;
ecam_base = device.mmioMap(bridge_id, 0) orelse { ecam_base = device.mmioMap(bridge_id, 0) orelse {
_ = runtime.system.write("/system/drviers/pci-bus: ECAM mmio_map failed\n"); _ = runtime.system.write("/system/drivers/pci-bus: ECAM mmio_map failed\n");
return false; return false;
}; };
@@ -116,17 +116,17 @@ fn initialise(endpoint: runtime.ipc.Handle) bool {
if (manager == null) runtime.system.sleep(20); if (manager == null) runtime.system.sleep(20);
} }
const h = manager orelse { const h = manager orelse {
_ = runtime.system.write("/system/drviers/pci-bus: no device manager to hello\n"); _ = runtime.system.write("/system/drivers/pci-bus: no device manager to hello\n");
return false; return false;
}; };
const hello = protocol.Hello{ .role = @intFromEnum(protocol.Role.bus), .device_id = bridge_id }; const hello = protocol.Hello{ .role = @intFromEnum(protocol.Role.bus), .device_id = bridge_id };
var reply: [protocol.message_maximum]u8 = undefined; var reply: [protocol.message_maximum]u8 = undefined;
const n = runtime.ipc.call(h, std.mem.asBytes(&hello), &reply) catch { const n = runtime.ipc.call(h, std.mem.asBytes(&hello), &reply) catch {
_ = runtime.system.write("/system/drviers/pci-bus: hello call failed\n"); _ = runtime.system.write("/system/drivers/pci-bus: hello call failed\n");
return false; return false;
}; };
if (n < protocol.reply_size or std.mem.bytesToValue(protocol.HelloReply, reply[0..protocol.reply_size]).status != 0) { if (n < protocol.reply_size or std.mem.bytesToValue(protocol.HelloReply, reply[0..protocol.reply_size]).status != 0) {
_ = runtime.system.write("/system/drviers/pci-bus: hello refused\n"); _ = runtime.system.write("/system/drivers/pci-bus: hello refused\n");
return false; return false;
} }
manager_handle = h; manager_handle = h;
@@ -159,7 +159,7 @@ fn scan() void {
} }
} }
} }
writeLine("/system/drviers/pci-bus: {d} functions found\n", .{found}); writeLine("/system/drivers/pci-bus: {d} functions found\n", .{found});
} }
/// Register one function under the bridge and report it to the manager. The /// Register one function under the bridge and report it to the manager. The
@@ -229,7 +229,7 @@ fn registerAndReport(bus: u64, dev: u64, function: u64, class_triple: u32) void
} }
const registered = device.register(bridge_id, &descriptor) orelse { const registered = device.register(bridge_id, &descriptor) orelse {
writeLine("/system/drviers/pci-bus: register refused for {d}:{d}.{d}\n", .{ bus, dev, function }); writeLine("/system/drivers/pci-bus: register refused for {d}:{d}.{d}\n", .{ bus, dev, function });
return; return;
}; };
const report = protocol.ChildAdded{ const report = protocol.ChildAdded{
@@ -240,7 +240,7 @@ fn registerAndReport(bus: u64, dev: u64, function: u64, class_triple: u32) void
}; };
var reply: [protocol.message_maximum]u8 = undefined; var reply: [protocol.message_maximum]u8 = undefined;
_ = runtime.ipc.call(manager_handle, std.mem.asBytes(&report), &reply) catch { _ = runtime.ipc.call(manager_handle, std.mem.asBytes(&report), &reply) catch {
writeLine("/system/drviers/pci-bus: child report for {d}:{d}.{d} failed\n", .{ bus, dev, function }); writeLine("/system/drivers/pci-bus: child report for {d}:{d}.{d} failed\n", .{ bus, dev, function });
}; };
} }
@@ -255,7 +255,7 @@ fn onMessage(message: []const u8, reply: []u8, sender: u32, capability: ?runtime
pub fn main(init: runtime.process.Init) void { pub fn main(init: runtime.process.Init) void {
const argument = init.arguments.get(1) orelse return; // bare (ramdisk sweep): stay silent const argument = init.arguments.get(1) orelse return; // bare (ramdisk sweep): stay silent
bridge_id = std.fmt.parseInt(u64, argument, 10) catch { bridge_id = std.fmt.parseInt(u64, argument, 10) catch {
writeLine("/system/drviers/pci-bus: malformed bridge device id '{s}'\n", .{argument}); writeLine("/system/drivers/pci-bus: malformed bridge device id '{s}'\n", .{argument});
return; return;
}; };
runtime.service.run(protocol.message_maximum, .{ runtime.service.run(protocol.message_maximum, .{
+32 -27
View File
@@ -207,6 +207,13 @@ fn eql(a: []const u8, b: []const u8) bool {
return std.mem.eql(u8, a, b); return std.mem.eql(u8, a, b);
} }
/// Whether the captured last-write buffer *contains* `needle`. Markers are
/// matched as substrings, not prefixes, so a service's source-path debug prefix
/// (`system/drivers/hpet: ok`) still satisfies a marker like `hpet: ok`.
fn bufferHas(needle: []const u8) bool {
return std.mem.indexOf(u8, process.write_buffer[0..process.write_len], needle) != null;
}
/// Non-destructive checks of the memory map and frame allocator. /// Non-destructive checks of the memory map and frame allocator.
fn smoke(boot_information: *const BootInformation) void { fn smoke(boot_information: *const BootInformation) void {
log("DANOS-TEST-BEGIN: smoke\n", .{}); log("DANOS-TEST-BEGIN: smoke\n", .{});
@@ -1376,7 +1383,7 @@ fn initTest(boot_information: *const BootInformation) void {
scheduler.setPriority(4); scheduler.setPriority(4);
const prefix = "init: heartbeat"; const prefix = "init: heartbeat";
const beat_ok = process.write_len >= prefix.len and eql(process.write_buffer[0..prefix.len], prefix); const beat_ok = bufferHas(prefix);
check("init produced repeated heartbeats (>=2)", process.write_count >= 2); check("init produced repeated heartbeats (>=2)", process.write_count >= 2);
check("heartbeat text arrived intact", beat_ok); check("heartbeat text arrived intact", beat_ok);
check("heartbeats came from user mode (CPL 3)", process.write_from_user); check("heartbeats came from user mode (CPL 3)", process.write_from_user);
@@ -1638,11 +1645,11 @@ fn vfsClientDeathTest(boot_information: *const BootInformation) void {
scheduler.setPriority(1); scheduler.setPriority(1);
var deadline = architecture.millis() + 10000; var deadline = architecture.millis() + 10000;
while (architecture.millis() < deadline) { while (architecture.millis() < deadline) {
if (process.write_len >= parked.len and eql(process.write_buffer[0..parked.len], parked)) break; if (bufferHas(parked)) break;
scheduler.yield(); scheduler.yield();
} }
scheduler.setPriority(4); scheduler.setPriority(4);
check("client parked holding an open handle", process.write_len >= parked.len and eql(process.write_buffer[0..parked.len], parked)); check("client parked holding an open handle", bufferHas(parked));
check("the kill is accepted", process.killProcess(me, client) == 0); check("the kill is accepted", process.killProcess(me, client) == 0);
var badge: u64 = 0; var badge: u64 = 0;
@@ -1655,11 +1662,11 @@ fn vfsClientDeathTest(boot_information: *const BootInformation) void {
scheduler.setPriority(1); scheduler.setPriority(1);
deadline = architecture.millis() + 10000; deadline = architecture.millis() + 10000;
while (architecture.millis() < deadline) { while (architecture.millis() < deadline) {
if (process.write_len >= released.len and eql(process.write_buffer[0..released.len], released)) break; if (bufferHas(released)) break;
scheduler.yield(); scheduler.yield();
} }
scheduler.setPriority(4); scheduler.setPriority(4);
check("the VFS released the dead client's handle", process.write_len >= released.len and eql(process.write_buffer[0..released.len], released)); check("the VFS released the dead client's handle", bufferHas(released));
result(); result();
} }
@@ -1701,8 +1708,8 @@ fn signalsTest(boot_information: *const BootInformation) void {
var saw_pass = false; var saw_pass = false;
var saw_fail = false; var saw_fail = false;
while (architecture.millis() < deadline and !saw_pass and !saw_fail) { while (architecture.millis() < deadline and !saw_pass and !saw_fail) {
if (process.write_len >= pass_marker.len and eql(process.write_buffer[0..pass_marker.len], pass_marker)) saw_pass = true; if (bufferHas(pass_marker)) saw_pass = true;
if (process.write_len >= fail_marker.len and eql(process.write_buffer[0..fail_marker.len], fail_marker)) saw_fail = true; if (bufferHas(fail_marker)) saw_fail = true;
scheduler.yield(); scheduler.yield();
} }
scheduler.setPriority(4); scheduler.setPriority(4);
@@ -1864,13 +1871,11 @@ fn pciScanTest(boot_information: *const BootInformation) void {
scheduler.setPriority(1); scheduler.setPriority(1);
var deadline = architecture.millis() + 15000; var deadline = architecture.millis() + 15000;
while (architecture.millis() < deadline and reported == 0) { while (architecture.millis() < deadline and reported == 0) {
if (process.write_len > count_prefix.len + count_suffix.len and eql(process.write_buffer[0..count_prefix.len], count_prefix)) {
const line = process.write_buffer[0..process.write_len]; const line = process.write_buffer[0..process.write_len];
const digits_end = std.mem.indexOf(u8, line, count_suffix) orelse { if (std.mem.indexOf(u8, line, count_prefix)) |start| {
scheduler.yield(); if (std.mem.indexOf(u8, line, count_suffix)) |digits_end| {
continue; reported = std.fmt.parseInt(u32, line[start + count_prefix.len .. digits_end], 10) catch 0;
}; }
reported = std.fmt.parseInt(u32, line[count_prefix.len..digits_end], 10) catch 0;
} }
scheduler.yield(); scheduler.yield();
} }
@@ -1894,7 +1899,7 @@ fn pciScanTest(boot_information: *const BootInformation) void {
deadline = architecture.millis() + 15000; deadline = architecture.millis() + 15000;
var restarted = false; var restarted = false;
while (architecture.millis() < deadline and !restarted) { while (architecture.millis() < deadline and !restarted) {
if (process.write_len >= restart_marker.len and eql(process.write_buffer[0..restart_marker.len], restart_marker)) restarted = true; if (bufferHas(restart_marker)) restarted = true;
scheduler.yield(); scheduler.yield();
} }
scheduler.setPriority(4); scheduler.setPriority(4);
@@ -1906,7 +1911,7 @@ fn pciScanTest(boot_information: *const BootInformation) void {
deadline = architecture.millis() + 15000; deadline = architecture.millis() + 15000;
var seen = false; var seen = false;
while (architecture.millis() < deadline and !seen) { while (architecture.millis() < deadline and !seen) {
if (process.write_len >= marker.len and eql(process.write_buffer[0..marker.len], marker)) seen = true; if (bufferHas(marker)) seen = true;
scheduler.yield(); scheduler.yield();
} }
scheduler.setPriority(4); scheduler.setPriority(4);
@@ -2035,12 +2040,12 @@ fn supervisionTest(boot_information: *const BootInformation) void {
scheduler.setPriority(1); scheduler.setPriority(1);
const deadline = architecture.millis() + 10000; const deadline = architecture.millis() + 10000;
while (architecture.millis() < deadline) { while (architecture.millis() < deadline) {
if (process.write_len >= marker.len and eql(process.write_buffer[0..marker.len], marker)) break; if (bufferHas(marker)) break;
scheduler.yield(); scheduler.yield();
} }
scheduler.setPriority(4); scheduler.setPriority(4);
const ok = process.write_len >= marker.len and eql(process.write_buffer[0..marker.len], marker); const ok = bufferHas(marker);
if (!ok and process.write_len > 0) log("DANOS-SUPERVISION: got \"{s}\"\n", .{process.write_buffer[0..process.write_len]}); if (!ok and process.write_len > 0) log("DANOS-SUPERVISION: got \"{s}\"\n", .{process.write_buffer[0..process.write_len]});
check("the supervisor completed every step (spawn/list/kill/notify)", ok); check("the supervisor completed every step (spawn/list/kill/notify)", ok);
check("it ran in user mode (CPL 3)", process.write_from_user); check("it ran in user mode (CPL 3)", process.write_from_user);
@@ -2120,12 +2125,12 @@ fn vfsTest(boot_information: *const BootInformation) void {
scheduler.setPriority(1); scheduler.setPriority(1);
const deadline = architecture.millis() + 10000; const deadline = architecture.millis() + 10000;
while (architecture.millis() < deadline) { while (architecture.millis() < deadline) {
if (process.write_len >= prefix.len and eql(process.write_buffer[0..prefix.len], prefix) and process.write_count >= 2) break; if (bufferHas(prefix) and process.write_count >= 2) break;
scheduler.yield(); scheduler.yield();
} }
scheduler.setPriority(4); scheduler.setPriority(4);
const ok = process.write_len >= prefix.len and eql(process.write_buffer[0..prefix.len], prefix); const ok = bufferHas(prefix);
check("client completed the VFS round trip (open/write/read matched)", ok); check("client completed the VFS round trip (open/write/read matched)", ok);
check("the round trip ran repeatedly (server stays up)", process.write_count >= 2); check("the round trip ran repeatedly (server stays up)", process.write_count >= 2);
check("client syscalls came from user mode (CPL 3)", process.write_from_user); check("client syscalls came from user mode (CPL 3)", process.write_from_user);
@@ -2165,12 +2170,12 @@ fn inputTest(boot_information: *const BootInformation) void {
scheduler.setPriority(1); scheduler.setPriority(1);
const deadline = architecture.millis() + 12000; const deadline = architecture.millis() + 12000;
while (architecture.millis() < deadline) { while (architecture.millis() < deadline) {
if (process.write_len >= prefix.len and eql(process.write_buffer[0..prefix.len], prefix) and process.write_count >= 2) break; if (bufferHas(prefix) and process.write_count >= 2) break;
scheduler.yield(); scheduler.yield();
} }
scheduler.setPriority(4); scheduler.setPriority(4);
const ok = process.write_len >= prefix.len and eql(process.write_buffer[0..prefix.len], prefix); const ok = bufferHas(prefix);
check("a subscriber received a broadcast key event over IPC (source -> service -> subscriber)", ok); check("a subscriber received a broadcast key event over IPC (source -> service -> subscriber)", ok);
check("events kept flowing (service + async send stay up)", process.write_count >= 2); check("events kept flowing (service + async send stay up)", process.write_count >= 2);
check("client syscalls came from user mode (CPL 3)", process.write_from_user); check("client syscalls came from user mode (CPL 3)", process.write_from_user);
@@ -2262,12 +2267,12 @@ fn hpetTest(boot_information: *const BootInformation) void {
scheduler.setPriority(1); scheduler.setPriority(1);
const deadline = architecture.millis() + 10000; const deadline = architecture.millis() + 10000;
while (architecture.millis() < deadline) { while (architecture.millis() < deadline) {
if (process.write_len >= prefix.len and eql(process.write_buffer[0..prefix.len], prefix) and process.write_count >= 2) break; if (bufferHas(prefix) and process.write_count >= 2) break;
scheduler.yield(); scheduler.yield();
} }
scheduler.setPriority(4); scheduler.setPriority(4);
const ok = process.write_len >= prefix.len and eql(process.write_buffer[0..prefix.len], prefix); const ok = bufferHas(prefix);
check("user driver mapped HPET MMIO and was woken by its interrupt", ok); check("user driver mapped HPET MMIO and was woken by its interrupt", ok);
check("driver syscalls came from user mode (CPL 3)", process.write_from_user); check("driver syscalls came from user mode (CPL 3)", process.write_from_user);
check("kernel routed and re-armed the HPET's line at the I/O APIC", hpetRouteOk()); check("kernel routed and re-armed the HPET's line at the I/O APIC", hpetRouteOk());
@@ -2368,12 +2373,12 @@ fn busTest(boot_information: *const BootInformation) void {
scheduler.setPriority(1); scheduler.setPriority(1);
const deadline = architecture.millis() + 10000; const deadline = architecture.millis() + 10000;
while (architecture.millis() < deadline) { while (architecture.millis() < deadline) {
if (process.write_len >= prefix.len and eql(process.write_buffer[0..prefix.len], prefix)) break; if (bufferHas(prefix)) break;
scheduler.yield(); scheduler.yield();
} }
scheduler.setPriority(4); scheduler.setPriority(4);
const ok = process.write_len >= prefix.len and eql(process.write_buffer[0..prefix.len], prefix); const ok = bufferHas(prefix);
check("bus driver published children and the kernel refused an out-of-window one", ok); check("bus driver published children and the kernel refused an out-of-window one", ok);
check("driver syscalls came from user mode (CPL 3)", process.write_from_user); check("driver syscalls came from user mode (CPL 3)", process.write_from_user);
check("every registered child is contained in its parent", childrenContained()); check("every registered child is contained in its parent", childrenContained());
@@ -2417,12 +2422,12 @@ fn deviceManagerTest(boot_information: *const BootInformation) void {
scheduler.setPriority(1); scheduler.setPriority(1);
const deadline = architecture.millis() + 10000; const deadline = architecture.millis() + 10000;
while (architecture.millis() < deadline) { while (architecture.millis() < deadline) {
if (process.write_len >= prefix.len and eql(process.write_buffer[0..prefix.len], prefix)) break; if (bufferHas(prefix)) break;
scheduler.yield(); scheduler.yield();
} }
scheduler.setPriority(4); scheduler.setPriority(4);
const ok = process.write_len >= prefix.len and eql(process.write_buffer[0..prefix.len], prefix); const ok = bufferHas(prefix);
check("device manager matched the timer and system_spawn'd hpet, which came up", ok); check("device manager matched the timer and system_spawn'd hpet, which came up", ok);
check("its syscalls came from user mode (CPL 3)", process.write_from_user); check("its syscalls came from user mode (CPL 3)", process.write_from_user);
result(); result();