node: add local_time and increment it by a fixed amount any time a task runs

This commit is contained in:
2026-06-08 10:05:52 +02:00
parent 4e3cae8cc8
commit 92f301ea40
3 changed files with 146 additions and 178 deletions
+2 -9
View File
@@ -868,14 +868,7 @@ fn fileClose(userdata: ?*anyopaque, files: []const File) void {
}
}
fn fileWritePositional(
userdata: ?*anyopaque,
file : File,
header : []const u8,
data : []const []const u8,
splat : usize,
offset : u64
) File.WritePositionalError!usize {
fn fileWritePositional(userdata: ?*anyopaque, file: File, header: []const u8, data: []const []const u8, splat: usize, offset: u64) File.WritePositionalError!usize {
const node: *Node = @ptrCast(@alignCast(userdata.?));
var cursor = std.math.cast(usize, offset) orelse return File.WritePositionalError.FileTooBig;
var copied: usize = 0;
@@ -1201,7 +1194,7 @@ fn now(userdata: ?*anyopaque, clock: Clock) Timestamp {
// TODO: Return an appropriate time for each clock
_ = clock;
return .{ .nanoseconds = node.scheduler.current_time * 1000 };
return .{ .nanoseconds = node.local_time * 1000 };
}
fn clockResolution(userdata: ?*anyopaque, clock: Clock) Clock.ResolutionError!Duration {
+21 -51
View File
@@ -6,7 +6,7 @@ const Network = @import("network.zig");
const Scheduler = @import("scheduler.zig");
const ioInterface = @import("io_interface.zig");
const MAX_DESCRIPTORS = 1<<10;
const MAX_DESCRIPTORS = 1 << 10;
const Node = @This();
const Handle = i32;
@@ -15,7 +15,6 @@ pub const TaskID = Scheduler.TaskID;
const NestedEntryPoint = Scheduler.NestedEntryPoint;
const Descriptor = struct {
const Kind = enum {
dir,
file,
@@ -24,14 +23,15 @@ const Descriptor = struct {
unused,
};
kind : Kind = .unused,
dir : FileSystem.OpenDir = undefined,
file : FileSystem.OpenFile = undefined,
kind: Kind = .unused,
dir: FileSystem.OpenDir = undefined,
file: FileSystem.OpenFile = undefined,
listen: Network.ListenSocket = undefined,
conn : Network.ConnSocket = undefined,
conn: Network.ConnSocket = undefined,
};
gpa: Allocator,
local_time: u64,
arena: std.heap.ArenaAllocator,
argv: [][*:0]const u8,
environ_map: std.process.Environ.Map,
@@ -52,7 +52,7 @@ fn splitCommandArguments(command: []const u8, arena: Allocator) Allocator.Error!
// Count how many arguments there are
var count: usize = 0;
while (cursor < command.len) {
if (command[cursor] != ' ' and (cursor == 0 or command[cursor-1] == ' '))
if (command[cursor] != ' ' and (cursor == 0 or command[cursor - 1] == ' '))
count += 1;
cursor += 1;
}
@@ -80,16 +80,9 @@ fn splitCommandArguments(command: []const u8, arena: Allocator) Allocator.Error!
return result;
}
pub fn init(
self : *Node,
real_io : std.Io,
scheduler: *Scheduler,
network : *Network,
command : []const u8,
addresses: []const u32,
gpa : Allocator
) !void {
pub fn init(self: *Node, real_io: std.Io, scheduler: *Scheduler, network: *Network, command: []const u8, addresses: []const u32, gpa: Allocator) !void {
self.gpa = gpa;
self.local_time = 0;
self.arena = .init(gpa);
self.scheduler = scheduler;
try self.file_system.init(gpa);
@@ -183,11 +176,11 @@ fn unusedDesc(self: *Node) ?*Descriptor {
return null;
}
const HandleError = error {
const HandleError = error{
InvalidHandle,
};
pub const CancelError = error {
pub const CancelError = error{
Canceled,
};
@@ -237,14 +230,10 @@ pub const CreateDirError = HandleError || FileSystem.CreateError || CancelError;
pub fn createDir(self: *Node, parent: ?Handle, path: []const u8) CreateDirError!void {
try self.scheduler.sleep(10);
return self.file_system.createDir(
path,
try self.handleToOpenDirOrNULL(parent),
self.gpa
);
return self.file_system.createDir(path, try self.handleToOpenDirOrNULL(parent), self.gpa);
}
pub const OpenDirError = error {
pub const OpenDirError = error{
DescriptorLimit,
} || HandleError || FileSystem.OpenError || CancelError;
@@ -285,36 +274,24 @@ pub const CreateFileError = HandleError || FileSystem.CreateError || CancelError
pub fn createFile(self: *Node, parent: ?Handle, path: []const u8) CreateFileError!void {
try self.scheduler.sleep(10);
return self.file_system.createFile(
path,
try self.handleToOpenDirOrNULL(parent),
self.gpa
);
return self.file_system.createFile(path, try self.handleToOpenDirOrNULL(parent), self.gpa);
}
pub const DeleteFileError = HandleError || FileSystem.DeleteFileError || CancelError;
pub fn deleteFile(self: *Node, parent: ?Handle, path: []const u8) DeleteFileError!void {
try self.scheduler.sleep(10);
return self.file_system.deleteFile(
path,
try self.handleToOpenDirOrNULL(parent),
self.gpa
);
return self.file_system.deleteFile(path, try self.handleToOpenDirOrNULL(parent), self.gpa);
}
pub const DeleteDirError = HandleError || FileSystem.DeleteDirError || CancelError;
pub fn deleteDir(self: *Node, parent: ?Handle, path: []const u8) DeleteDirError!void {
try self.scheduler.sleep(10);
return self.file_system.deleteDir(
path,
try self.handleToOpenDirOrNULL(parent),
self.gpa
);
return self.file_system.deleteDir(path, try self.handleToOpenDirOrNULL(parent), self.gpa);
}
pub const OpenFileError = error {
pub const OpenFileError = error{
DescriptorLimit,
} || HandleError || FileSystem.OpenError || CancelError;
@@ -383,14 +360,7 @@ fn writeToStderr(self: *Node, source: []const u8) void {
pub const WriteFileError = HandleError || Allocator.Error || CancelError;
pub fn writeFile(
self : *Node,
handle: Handle,
offset: ?usize,
header: []const u8,
source: []const []const u8
) WriteFileError!usize {
pub fn writeFile(self: *Node, handle: Handle, offset: ?usize, header: []const u8, source: []const []const u8) WriteFileError!usize {
try self.scheduler.sleep(100);
if (handle == 0) {
@@ -441,7 +411,7 @@ pub fn seekFileBy(self: *Node, handle: Handle, offset: i64) SeekFileError!void {
}
pub const Address = Network.Address;
pub const ListenError = error {
pub const ListenError = error{
DescriptorLimit,
} || Network.ListenError || CancelError;
@@ -453,7 +423,7 @@ pub fn listen(self: *Node, address: Address) ListenError!Handle {
return self.descToHandle(desc);
}
pub const AcceptError = error {
pub const AcceptError = error{
DescriptorLimit,
} || HandleError || Network.AcceptError || CancelError;
@@ -472,7 +442,7 @@ pub fn accept(self: *Node, handle: Handle) AcceptError!Handle {
}
}
pub const ConnectError = error {
pub const ConnectError = error{
DescriptorLimit,
} || Network.ConnectError || CancelError;
+18 -13
View File
@@ -4,8 +4,8 @@ const Node = @import("node.zig");
const Scheduler = @This();
pub const MainEntryPoint = *const fn(std.process.Init) anyerror!void;
pub const NestedEntryPoint = *const fn(context: *const anyopaque) void;
pub const MainEntryPoint = *const fn (std.process.Init) anyerror!void;
pub const NestedEntryPoint = *const fn (context: *const anyopaque) void;
pub const EntryPoint = union(enum) {
main: MainEntryPoint,
@@ -26,6 +26,7 @@ const ContextSwitch = extern struct {
const STACK_CANARY_SIZE = 256;
const STACK_CANARY_BYTE = 0xa5;
const TASK_RUN_COST_US = 50;
pub const TaskID = u64;
@@ -38,13 +39,13 @@ const State = enum {
};
const Task = struct {
id : TaskID,
regs : Registers,
stack : []align(16) u8,
entry : EntryPoint,
id: TaskID,
regs: Registers,
stack: []align(16) u8,
entry: EntryPoint,
context: ?*const anyopaque,
state : State,
node : *Node,
state: State,
node: *Node,
// If this is a subtask, parent_id refers to the parent.
// The cancel flag is set when the parent requests cancellation.
@@ -107,7 +108,6 @@ fn spawnInner(
parent_id: ?TaskID,
context: ?*const anyopaque,
) !*Task {
if (stack_size > std.math.maxInt(usize) - STACK_CANARY_SIZE)
return Allocator.Error.OutOfMemory;
@@ -125,7 +125,7 @@ fn spawnInner(
const id = self.next_task_id;
defer self.next_task_id += 1;
const task = Task {
const task = Task{
.id = id,
.regs = .{
.rsp = stack_top,
@@ -196,6 +196,9 @@ fn findBlockedTaskWithLowestWakeupTime(self: *Scheduler) ?*Task {
fn advanceTimeAndUnblockTasks(self: *Scheduler, new_time: u64) void {
std.debug.assert(self.current_time < new_time);
self.current_time = new_time;
for (self.tasks.items) |task| {
task.node.local_time = @max(task.node.local_time, new_time);
}
for (self.tasks.items) |*task| {
if (task.state == .blocked) {
if (task.wakeup_time) |wakeup_time| {
@@ -229,9 +232,7 @@ fn advanceTimeAndPickTask(self: *Scheduler) ?*Task {
}
pub fn scheduleOne(self: *Scheduler) bool {
const task = self.findTaskWithState(.ready)
orelse self.advanceTimeAndPickTask()
orelse return false;
const task = self.findTaskWithState(.ready) orelse self.advanceTimeAndPickTask() orelse return false;
const id = task.id;
self.current_id = id;
task.state = .running;
@@ -296,6 +297,7 @@ fn taskStart(self: *Scheduler) callconv(.c) noreturn {
current.wakeup_time = null;
current.wakeup_tasks = null;
current.wakeup_futex = null;
current.node.local_time += TASK_RUN_COST_US;
if (current.parent_id) |parent_id| {
if (self.findTaskByID(parent_id)) |parent| {
if (taskIsWaitingFor(parent, current.id)) {
@@ -322,6 +324,7 @@ pub fn sleep(self: *Scheduler, delta_us: u64) !void {
current.wakeup_time = self.current_time + delta_us;
current.wakeup_tasks = null;
current.wakeup_futex = null;
current.node.local_time += TASK_RUN_COST_US;
contextSwitch(&current.regs, &self.regs);
try self.checkCancel();
}
@@ -341,6 +344,7 @@ pub fn futexWaitUncancelable(self: *Scheduler, ptr: *const u32, expected: u32) v
current.wakeup_time = null;
current.wakeup_tasks = null;
current.wakeup_futex = ptr;
current.node.local_time += TASK_RUN_COST_US;
contextSwitch(&current.regs, &self.regs);
}
@@ -385,6 +389,7 @@ pub fn wait(self: *Scheduler, ids: []const TaskID) !TaskID {
task.wakeup_time = null;
task.wakeup_tasks = ids;
task.wakeup_futex = null;
task.node.local_time += TASK_RUN_COST_US;
contextSwitch(&task.regs, &self.regs);
try self.checkCancel();
}