C2: migrate consumers off the runtime shim to direct concern-module imports
Every user binary and the two device-logic library modules (pci, usb) now
`@import` the concern modules directly instead of aliasing through `runtime`:
runtime.ipc/process/time/service/input/block/display -> @import("<module>")
runtime.device / runtime.device_manager -> @import("driver")
runtime.fs -> @import("file-system")
runtime.Thread -> @import("thread").Thread
runtime.system.{write,writeRecord,klog*} -> logging.*
runtime.system.{sleep,timerOnce,wallClock,clock} -> time.*
runtime.system.{spawn*,kill,exit,yield,processes,...}-> process.*
runtime.system.{mmap,munmap,PROT_*} -> memory.*
runtime.dma.* / runtime.shared_memory.* / runtime.allocator -> memory.*
Each consumer keeps its own alias name (e.g. `const device = @import("driver")`),
so call sites are unchanged and there are no collisions with local `driver`
variables. build.zig now injects the concern modules into every user binary via
`default_imports`; pci/usb module import lists were updated to match.
The `runtime` and `system` shims remain for one more step (root.zig still uses
runtime); they are deleted in C5. Nothing but root.zig imports `runtime` now.
Verified: zig build, zig build test, and 17 QEMU cases (smoke, device-manager,
logger, fat-mount, fat-mutations, usb-storage, usb-hid, display-native,
virtio-gpu, input, thread-spawn, thread-mutex, process-kill, shared-memory,
driver-restart, acpi-ps2, pci-scan).
This commit is contained in:
@@ -5,15 +5,17 @@
|
||||
//! kernel test spawns it alongside init.
|
||||
|
||||
const std = @import("std");
|
||||
const runtime = @import("runtime");
|
||||
const fs = runtime.fs;
|
||||
const fs = @import("file-system");
|
||||
const process = @import("process");
|
||||
const time = @import("time");
|
||||
const logging = @import("logging");
|
||||
|
||||
fn writeLine(comptime fmt: []const u8, arguments: anytype) void {
|
||||
var line: [128]u8 = undefined;
|
||||
_ = runtime.system.write(std.fmt.bufPrint(&line, fmt, arguments) catch return);
|
||||
_ = logging.write(std.fmt.bufPrint(&line, fmt, arguments) catch return);
|
||||
}
|
||||
|
||||
pub fn main(init: runtime.process.Init) void {
|
||||
pub fn main(init: process.Init) void {
|
||||
_ = init;
|
||||
|
||||
// Wait for /mnt/usb to be mounted — the fat server races us at boot (it must
|
||||
@@ -22,10 +24,10 @@ pub fn main(init: runtime.process.Init) void {
|
||||
var tries: u32 = 0;
|
||||
while (opened == null and tries < 1400) : (tries += 1) {
|
||||
opened = fs.openDirectory("/mnt/usb");
|
||||
if (opened == null) runtime.system.sleep(50);
|
||||
if (opened == null) time.sleepMillis(50);
|
||||
}
|
||||
var dir = opened orelse {
|
||||
_ = runtime.system.write("fat-test: /mnt/usb never became available\n");
|
||||
_ = logging.write("fat-test: /mnt/usb never became available\n");
|
||||
return;
|
||||
};
|
||||
|
||||
@@ -47,7 +49,7 @@ pub fn main(init: runtime.process.Init) void {
|
||||
const n = file.read(&magic) orelse 0;
|
||||
file.close();
|
||||
if (n == 4 and magic[0] == 0x7F and magic[1] == 'E' and magic[2] == 'L' and magic[3] == 'F') {
|
||||
_ = runtime.system.write("fat-test: read /mnt/usb/system/kernel ELF magic ok\n");
|
||||
_ = logging.write("fat-test: read /mnt/usb/system/kernel ELF magic ok\n");
|
||||
} else {
|
||||
writeLine("fat-test: /mnt/usb/system/kernel read {d} bytes (not ELF magic)\n", .{n});
|
||||
}
|
||||
@@ -68,12 +70,12 @@ pub fn main(init: runtime.process.Init) void {
|
||||
writeLine("fat-test: mtime {d}\n", .{attrs.mtime});
|
||||
mtime_ok = attrs.mtime > 1_577_836_800; // after 2020-01-01
|
||||
}
|
||||
if (mtime_ok) _ = runtime.system.write("fat-test: mtime ok\n");
|
||||
if (mtime_ok) _ = logging.write("fat-test: mtime ok\n");
|
||||
|
||||
// Rename it, then read from the new name and confirm the old name is gone.
|
||||
const renamed = fs.rename("/mnt/usb/TESTDIR/HELLO.TXT", "/mnt/usb/TESTDIR/RENAMED.TXT");
|
||||
const old_gone = !fs.exists("/mnt/usb/TESTDIR/HELLO.TXT");
|
||||
if (renamed and old_gone) _ = runtime.system.write("fat-test: rename ok\n");
|
||||
if (renamed and old_gone) _ = logging.write("fat-test: rename ok\n");
|
||||
var readback = false;
|
||||
if (fs.open("/mnt/usb/TESTDIR/RENAMED.TXT", .{})) |reopened| {
|
||||
var f = reopened;
|
||||
@@ -85,19 +87,19 @@ pub fn main(init: runtime.process.Init) void {
|
||||
const removed = fs.remove("/mnt/usb/TESTDIR/RENAMED.TXT");
|
||||
const gone = !fs.exists("/mnt/usb/TESTDIR/RENAMED.TXT");
|
||||
if (wrote and mtime_ok and renamed and old_gone and readback and removed and gone) {
|
||||
_ = runtime.system.write("fat-test: mutations ok\n");
|
||||
_ = logging.write("fat-test: mutations ok\n");
|
||||
} else {
|
||||
writeLine("fat-test: mutations FAILED (wrote={} mtime={} renamed={} oldgone={} read={} removed={} gone={})\n", .{ wrote, mtime_ok, renamed, old_gone, readback, removed, gone });
|
||||
}
|
||||
} else {
|
||||
_ = runtime.system.write("fat-test: mkdir /mnt/usb/TESTDIR failed\n");
|
||||
_ = logging.write("fat-test: mkdir /mnt/usb/TESTDIR failed\n");
|
||||
}
|
||||
|
||||
if (count > 0) {
|
||||
while (true) {
|
||||
_ = runtime.system.write("fat-test: ok\n");
|
||||
runtime.system.sleep(1000);
|
||||
_ = logging.write("fat-test: ok\n");
|
||||
time.sleepMillis(1000);
|
||||
}
|
||||
}
|
||||
_ = runtime.system.write("fat-test: root listing was empty\n");
|
||||
_ = logging.write("fat-test: root listing was empty\n");
|
||||
}
|
||||
|
||||
+29
-23
@@ -10,19 +10,25 @@
|
||||
//! it.
|
||||
|
||||
const std = @import("std");
|
||||
const runtime = @import("runtime");
|
||||
const ipc = @import("ipc");
|
||||
const process = @import("process");
|
||||
const service = @import("service");
|
||||
const time = @import("time");
|
||||
const block = @import("block");
|
||||
const file_system = @import("file-system");
|
||||
const memory = @import("memory");
|
||||
const logging = @import("logging");
|
||||
const engine = @import("engine.zig");
|
||||
const on_disk = @import("on-disk.zig");
|
||||
const vfs_protocol = @import("vfs-protocol");
|
||||
const dma = runtime.dma;
|
||||
|
||||
const mount_point = "/mnt/usb";
|
||||
|
||||
// The engine's BlockDevice, backed by the `.block` driver plus a DMA bounce
|
||||
// buffer the driver reads/writes by physical address.
|
||||
const IpcBlock = struct {
|
||||
device: runtime.block.Device,
|
||||
bounce: dma.Region, // engine.max_transfer_sectors * 512 bytes
|
||||
device: block.Device,
|
||||
bounce: memory.DmaRegion, // engine.max_transfer_sectors * 512 bytes
|
||||
|
||||
fn readBlocks(context: *anyopaque, lba: u64, count: u32, buffer: []u8) bool {
|
||||
const self: *IpcBlock = @ptrCast(@alignCast(context));
|
||||
@@ -89,17 +95,17 @@ fn fail(out: []u8) usize {
|
||||
const mount_retry_ms = 500;
|
||||
|
||||
var mounted = false;
|
||||
var service_endpoint: runtime.ipc.Handle = 0;
|
||||
var service_endpoint: ipc.Handle = 0;
|
||||
|
||||
fn initialise(endpoint: runtime.ipc.Handle) bool {
|
||||
fn initialise(endpoint: ipc.Handle) bool {
|
||||
service_endpoint = endpoint;
|
||||
_ = runtime.system.write("/system/services/fat: starting, waiting for a block device\n");
|
||||
_ = logging.write("/system/services/fat: starting, waiting for a block device\n");
|
||||
// With the router in the kernel, clients hold OUR node ids directly; sweep
|
||||
// a dead client's open handles via the published exit events (the pattern
|
||||
// the old userspace router used for its own table).
|
||||
_ = runtime.process.subscribeExits(endpoint);
|
||||
_ = process.subscribeExits(endpoint);
|
||||
tryBringUp();
|
||||
if (!mounted) _ = runtime.system.timerOnce(endpoint, mount_retry_ms);
|
||||
if (!mounted) _ = time.timerOnce(endpoint, mount_retry_ms);
|
||||
return true; // serve regardless: requests fail politely until storage mounts
|
||||
}
|
||||
|
||||
@@ -107,12 +113,12 @@ fn initialise(endpoint: runtime.ipc.Handle) bool {
|
||||
/// `mounted` on success; a failure leaves everything untouched for the next tick.
|
||||
fn tryBringUp() void {
|
||||
if (mounted) return;
|
||||
const device = runtime.block.tryOpen() orelse return;
|
||||
const device = block.tryOpen() orelse return;
|
||||
const geometry = device.geometry() orelse {
|
||||
_ = runtime.system.write("/system/services/fat: block geometry unavailable\n");
|
||||
_ = logging.write("/system/services/fat: block geometry unavailable\n");
|
||||
return;
|
||||
};
|
||||
const bounce = dma.alloc(engine.max_transfer_sectors * 512, dma.coherent) orelse return;
|
||||
const bounce = memory.dmaAlloc(engine.max_transfer_sectors * 512, memory.dma_coherent) orelse return;
|
||||
ipc_block = .{ .device = device, .bounce = bounce };
|
||||
|
||||
const block_device = engine.BlockDevice{
|
||||
@@ -123,7 +129,7 @@ fn tryBringUp() void {
|
||||
.writeBlocksFn = IpcBlock.writeBlocks,
|
||||
};
|
||||
filesystem = engine.FileSystem.mount(block_device) orelse {
|
||||
_ = runtime.system.write("/system/services/fat: not a FAT filesystem\n");
|
||||
_ = logging.write("/system/services/fat: not a FAT filesystem\n");
|
||||
return;
|
||||
};
|
||||
std.log.info("mounted FAT ({s}, {d} clusters, partition lba {d})", .{ @tagName(filesystem.geometry.fat_type), filesystem.geometry.cluster_count, filesystem.base_lba });
|
||||
@@ -131,30 +137,30 @@ fn tryBringUp() void {
|
||||
// Mount ourselves into the kernel VFS at /mnt/usb — and serve /var from the
|
||||
// volume's /var subtree, so FHS paths (the logger's /var/log) stay decoupled
|
||||
// from which volume carries them.
|
||||
if (runtime.fs.mount(mount_point, endpointForMount())) {
|
||||
if (file_system.mount(mount_point, endpointForMount())) {
|
||||
std.log.info("mounted {s}", .{mount_point});
|
||||
} else {
|
||||
_ = runtime.system.write("/system/services/fat: could not mount /mnt/usb\n");
|
||||
_ = logging.write("/system/services/fat: could not mount /mnt/usb\n");
|
||||
}
|
||||
if (runtime.fs.mountRewritten("/var", endpointForMount(), "/var")) {
|
||||
if (file_system.mountRewritten("/var", endpointForMount(), "/var")) {
|
||||
std.log.info("mounted /var", .{});
|
||||
} else {
|
||||
_ = runtime.system.write("/system/services/fat: could not mount /var\n");
|
||||
_ = logging.write("/system/services/fat: could not mount /var\n");
|
||||
}
|
||||
mounted = true;
|
||||
}
|
||||
|
||||
fn endpointForMount() runtime.ipc.Handle {
|
||||
fn endpointForMount() ipc.Handle {
|
||||
return service_endpoint;
|
||||
}
|
||||
|
||||
/// A subscribed process-exit event: release every open handle the dead client
|
||||
/// held, so a crashed reader can't pin table slots (or, later, locks).
|
||||
fn onNotification(badge: u64) void {
|
||||
const got = runtime.ipc.Received{ .len = 0, .badge = badge, .cap = null };
|
||||
const got = ipc.Received{ .len = 0, .badge = badge, .cap = null };
|
||||
if (got.isTimer()) {
|
||||
tryBringUp();
|
||||
if (!mounted) _ = runtime.system.timerOnce(service_endpoint, mount_retry_ms);
|
||||
if (!mounted) _ = time.timerOnce(service_endpoint, mount_retry_ms);
|
||||
return;
|
||||
}
|
||||
if (!got.isChildExit()) return;
|
||||
@@ -199,7 +205,7 @@ fn handleOpen(out: []u8, path: []const u8, flags: u32, sender: u32) usize {
|
||||
return writeReply(out, .{ .status = 0, .node = index }, &.{});
|
||||
}
|
||||
|
||||
fn onMessage(message: []const u8, out: []u8, sender: u32, capability: ?runtime.ipc.Handle) usize {
|
||||
fn onMessage(message: []const u8, out: []u8, sender: u32, capability: ?ipc.Handle) usize {
|
||||
_ = capability;
|
||||
if (!mounted) return fail(out); // storage not up (yet): fail politely, clients retry
|
||||
if (message.len < vfs_protocol.request_size) return fail(out);
|
||||
@@ -208,7 +214,7 @@ fn onMessage(message: []const u8, out: []u8, sender: u32, capability: ?runtime.i
|
||||
|
||||
// Stamp create/write with the current wall-clock time (mtime). Cheap, and it
|
||||
// keeps the engine pure (it takes the time as data, not a syscall).
|
||||
filesystem.current_time_epoch = runtime.system.wallClock();
|
||||
filesystem.current_time_epoch = time.wallClock();
|
||||
|
||||
switch (request.operation) {
|
||||
.open => return handleOpen(out, payload[0..@min(payload.len, request.len)], request.flags, sender),
|
||||
@@ -287,7 +293,7 @@ fn onMessage(message: []const u8, out: []u8, sender: u32, capability: ?runtime.i
|
||||
}
|
||||
|
||||
pub fn main() void {
|
||||
runtime.service.run(vfs_protocol.message_maximum, .{
|
||||
service.run(vfs_protocol.message_maximum, .{
|
||||
.service = .fat,
|
||||
.init = initialise,
|
||||
.on_message = onMessage,
|
||||
|
||||
Reference in New Issue
Block a user