Files
Daniel Samson 0eb2420690 device-manager: delete the delegated-set scaffolding
The name list and its predicate existed so drivers could move to delegation
one at a time with the suite green throughout. Every driver is delegated
now, so the manager simply hands over whatever device a driver was assigned.

Deleting it caught a real consequence: crash-test finally got delegated too,
and it was still claiming its device — so it got AlreadyClaimed because it
already held it, exited, and the restart drill had nothing to restart. Its
own comment named what the case was really checking: "the respawn only
reaches this line because the kernel released the previous instance's claim
at death". That property still holds, by a different mechanism — the device
reverts to the manager on death and is handed to the replacement, which is
the same guarantee without the race it used to rely on.

All four delegation paths verified: the xHCI controller, the PCI bridge, the
PS/2 two-node singleton, and virtio-gpu's restart re-attach.

Run 3 complete. Suite 118/118.
2026-08-08 23:01:29 +01:00

55 lines
2.6 KiB
Zig

//! crash-test — a test fixture, not a driver: claims the device it is assigned,
//! hellos the device manager, announces itself, then faults on purpose. The
//! driver-restart scenario drives the manager's whole restart machinery with
//! it: fault → exit reason → backoff → respawn → the **same claim succeeding
//! again** (claim release on death, M17.1, through the manager's path) → the
//! crash-loop cap. Spawned bare (the initial-ramdisk sweep starts every bundled
//! binary), it exits silently so it cannot derange other tests.
const std = @import("std");
const channel = @import("channel");
const ipc = @import("ipc");
const process = @import("process");
const time = @import("time");
const device = @import("driver");
const logging = @import("logging");
const device_manager_protocol = @import("device-manager-protocol");
pub fn main(init: process.Init) void {
const argument = init.arguments.get(1) orelse return; // bare: stay silent
const assigned = std.fmt.parseInt(u64, argument, 10) catch return;
// The device arrived with the spawn — this fixture is delegated its hardware like
// any other driver, so it holds `assigned` before its first instruction and has
// nothing to claim (docs/os-development/device-authority.md).
//
// The property this scenario checks is unchanged, only its mechanism: a respawned
// instance still gets the device its predecessor held. It used to arrive because
// the kernel released the dead instance's claim and this one re-took it, racing
// anyone else who wanted it; now the device reverts to the manager on death and is
// handed to the replacement, which is the same guarantee without the race.
var manager: ?ipc.Handle = null;
var tries: u32 = 0;
while (manager == null and tries < 100) : (tries += 1) {
manager = channel.openEndpoint("device-manager");
if (manager == null) time.sleepMillis(20);
}
const h = manager orelse return;
// The assigned device is the packet's target, the manager's object addressing.
var packet: [device_manager_protocol.message_maximum]u8 = undefined;
const framed = device_manager_protocol.Protocol.encodeRequest(
.hello,
assigned,
.{ .role = @intFromEnum(device_manager_protocol.Role.device) },
&.{},
&packet,
) orelse return;
var reply: [device_manager_protocol.message_maximum]u8 = undefined;
_ = ipc.call(h, framed, &reply) catch return;
_ = logging.write("crash-test: faulting now\n");
const poison: *volatile u32 = @ptrFromInt(0xdead0000);
poison.* = 1; // the restart machinery's fuel: a real segmentation fault
}