diff --git a/docs/drivers.md b/docs/drivers.md index 2c72844..699149f 100644 --- a/docs/drivers.md +++ b/docs/drivers.md @@ -189,7 +189,7 @@ const hpet = findHpet(buf) orelse return; // device_enumerate, look for // class=timer with memory + irq _ = dev.claim(hpet.dev_id); // the capability const base = dev.mmioMap(hpet.dev_id, hpet.mmio).?; -const endpoint = ipc.createEndpoint().?; +const endpoint = ipc.createIpcEndpoint().?; // program the hardware over the mapping we were just handed reg(base, 0x100).* = level | int_enb | (hpet.gsi << 9); // timer 0 config diff --git a/library/runtime/ipc.zig b/library/runtime/ipc.zig index b9acac9..62fb8bc 100644 --- a/library/runtime/ipc.zig +++ b/library/runtime/ipc.zig @@ -24,8 +24,8 @@ inline fn failed(r: usize) bool { } /// Create a new endpoint owned by this process; returns its handle. -pub fn createEndpoint() ?Handle { - const r = sc.systemCall0(.create_endpoint); +pub fn createIpcEndpoint() ?Handle { + const r = sc.systemCall0(.create_ipc_endpoint); return if (failed(r)) null else r; } diff --git a/system/abi.zig b/system/abi.zig index acb7627..40779e6 100644 --- a/system/abi.zig +++ b/system/abi.zig @@ -32,7 +32,7 @@ pub const SystemCall = enum(u64) { sleep = 3, // sleep(ms): block the caller for ms milliseconds mmap = 4, // mmap(len, prot) -> base: grant zeroed, page-aligned user pages munmap = 5, // munmap(base, len): release pages from a prior mmap - create_endpoint = 6, // create_endpoint() -> handle: a new IPC endpoint + create_ipc_endpoint = 6, // create_ipc_endpoint() -> handle: a new IPC endpoint ipc_register = 7, // ipc_register(service_id, handle): publish an endpoint by well-known id ipc_lookup = 8, // ipc_lookup(service_id) -> handle: find a published endpoint ipc_call = 9, // ipc_call(h, message, len, reply, cap) -> reply_len: send + block for reply @@ -73,7 +73,7 @@ pub const dma_below_4g: u64 = 4; // physical address must fit 32 bits (legacy DM /// event loop can't disagree about which bit means "the hardware spoke". pub const notify_badge_bit: u64 = 1 << 63; -/// Well-known IPC service ids for the bootstrap name registry (create_endpoint + +/// Well-known IPC service ids for the bootstrap name registry (create_ipc_endpoint + /// ipc_register/ipc_lookup). Small integers, so no string interning is needed /// during bring-up. The VFS server registers under `vfs`; clients look it up. pub const ServiceId = enum(u32) { diff --git a/system/drivers/hpet/hpet.zig b/system/drivers/hpet/hpet.zig index 8d1fc87..b6afee2 100644 --- a/system/drivers/hpet/hpet.zig +++ b/system/drivers/hpet/hpet.zig @@ -115,8 +115,8 @@ pub fn main() void { // to raise exactly this line — the kernel will only bind the one it recorded. const gsi = hpet.gsi; - const endpoint = ipc.createEndpoint() orelse { - _ = runtime.system.write("hpet: create_endpoint failed\n"); + const endpoint = ipc.createIpcEndpoint() orelse { + _ = runtime.system.write("hpet: create_ipc_endpoint failed\n"); return; }; diff --git a/system/kernel/ipc-synchronous.zig b/system/kernel/ipc-synchronous.zig index fec1f7c..1288f00 100644 --- a/system/kernel/ipc-synchronous.zig +++ b/system/kernel/ipc-synchronous.zig @@ -73,7 +73,7 @@ pub const Endpoint = struct { notify_tail: u8 = 0, }; -pub fn createEndpoint() ?*Endpoint { +pub fn createIpcEndpoint() ?*Endpoint { const endpoint = heap.allocator().create(Endpoint) catch return null; endpoint.* = .{}; return endpoint; diff --git a/system/kernel/process.zig b/system/kernel/process.zig index 222221e..db6e414 100644 --- a/system/kernel/process.zig +++ b/system/kernel/process.zig @@ -145,7 +145,7 @@ fn system_call(state: *architecture.CpuState) void { .debug_write => systemDebugWrite(state), .mmap => systemMmap(state), .munmap => systemMunmap(state), - .create_endpoint => systemCreateEndpoint(state), + .create_ipc_endpoint => systemCreateIpcEndpoint(state), .ipc_register => systemIpcRegister(state), .ipc_lookup => systemIpcLookup(state), .ipc_call => systemIpcCall(state), @@ -162,6 +162,7 @@ fn system_call(state: *architecture.CpuState) void { .msi_bind => systemMsiBind(state), .io_read => systemIoRead(state), .io_write => systemIoWrite(state), + .clock => systemClock(state), _ => fail(state), } } @@ -171,10 +172,10 @@ fn failErr(state: *architecture.CpuState, errno: i64) void { architecture.setSystemCallResult(state, @bitCast(-errno)); } -/// create_endpoint() -> handle: allocate an endpoint and install it in the +/// create_ipc_endpoint() -> handle: allocate an endpoint and install it in the /// caller's handle table. -fn systemCreateEndpoint(state: *architecture.CpuState) void { - const endpoint = ipc.createEndpoint() orelse return failErr(state, ipc.ENOMEM); +fn systemCreateIpcEndpoint(state: *architecture.CpuState) void { + const endpoint = ipc.createIpcEndpoint() orelse return failErr(state, ipc.ENOMEM); const h = ipc.installHandle(scheduler.current(), endpoint); if (h < 0) { ipc.dropRef(endpoint); @@ -760,3 +761,12 @@ pub fn spawnProcess(image: []const u8, priority: u3) InitError!void { if (!scheduler.spawnUserLocked(aspace, parsed.entry, stack_virtual + page_size, priority)) return error.OutOfMemory; } + +/// clock() -> nanoseconds since boot: a monotonic time source. The kernel already owns +/// the scheduling timer and computes this for preemption, so surfacing it is pure +/// mechanism — no policy (wall-clock time, calendars, timezones are a user-space +/// service layered on top). It lets a driver bound a poll loop by real time instead of +/// a spin count, and time short delays. +fn systemClock(state: *architecture.CpuState) void { + architecture.setSystemCallResult(state, architecture.nanos()); +} \ No newline at end of file diff --git a/system/kernel/tests.zig b/system/kernel/tests.zig index cceeb8f..e9a7163 100644 --- a/system/kernel/tests.zig +++ b/system/kernel/tests.zig @@ -872,7 +872,7 @@ fn ipcClient() void { /// prove the block/wake and reply-routing paths. (Kernel tasks, so no user ELF.) fn ipcCallTest() void { log("DANOS-TEST-BEGIN: ipc-call\n", .{}); - ipc_endpoint = ipcsync.createEndpoint().?; + ipc_endpoint = ipcsync.createIpcEndpoint().?; ipc_replies_ok = false; ipc_done = false; scheduler.spawn(ipcServer, 5); // above this task, so the workers run @@ -900,7 +900,7 @@ var cap_done: bool = false; /// verify it, then reply handing back a capability of its own. fn capServer() void { const me = scheduler.current(); - cap_ep_y = ipcsync.createEndpoint().?; + cap_ep_y = ipcsync.createIpcEndpoint().?; const h_y = ipcsync.installHandle(me, cap_ep_y); // the handle to send back in the reply var reply_buffer: [8]u8 = .{0} ** 8; @@ -923,7 +923,7 @@ fn capServer() void { /// Client half of "open": mint a capability, send it in a call, receive one back. fn capClient() void { const me = scheduler.current(); - cap_ep_x = ipcsync.createEndpoint().?; + cap_ep_x = ipcsync.createIpcEndpoint().?; const h_x = ipcsync.installHandle(me, cap_ep_x); var message: [8]u8 = .{0} ** 8; @@ -945,7 +945,7 @@ fn capClient() void { /// equal) and was *shared*, not moved (refcount bumped to 2). fn capabilityTest() void { log("DANOS-TEST-BEGIN: ipc-cap\n", .{}); - cap_endpoint = ipcsync.createEndpoint().?; + cap_endpoint = ipcsync.createIpcEndpoint().?; cap_server_got_x = false; cap_client_got_y = false; cap_done = false; @@ -1017,7 +1017,7 @@ fn dmaTest() void { /// the device-claim check and lands its first real use with the first PCI driver. fn msiTest() void { log("DANOS-TEST-BEGIN: msi\n", .{}); - const endpoint = ipcsync.createEndpoint().?; + const endpoint = ipcsync.createIpcEndpoint().?; const flags = sync.enter(); const vector = irq.msiBind(endpoint, 0) catch { @@ -1567,7 +1567,7 @@ fn irqFreeTest() void { return; }; - const endpoint = ipcsync.createEndpoint() orelse { + const endpoint = ipcsync.createIpcEndpoint() orelse { check("allocated an endpoint", false); result(); return; diff --git a/system/services/vfs/vfs.zig b/system/services/vfs/vfs.zig index 2eb5313..df605e6 100644 --- a/system/services/vfs/vfs.zig +++ b/system/services/vfs/vfs.zig @@ -114,7 +114,7 @@ fn handle(message: []const u8, out: []u8) usize { } pub fn main() void { - const endpoint = runtime.ipc.createEndpoint() orelse { + const endpoint = runtime.ipc.createIpcEndpoint() orelse { _ = runtime.system.write("vfs: no endpoint\n"); return; };