diff --git a/src/io_interface.zig b/src/io_interface.zig index 813c6a1..826146d 100644 --- a/src/io_interface.zig +++ b/src/io_interface.zig @@ -4,25 +4,25 @@ const Node = @import("node.zig"); const Io = std.Io; const net = Io.net; -const Dir = Io.Dir; -const File = Io.File; -const Group = Io.Group; -const AnyFuture = Io.AnyFuture; -const ConcurrentError = Io.ConcurrentError; -const CancelProtection = Io.CancelProtection; -const Cancelable = Io.Cancelable; -const Timeout = Io.Timeout; -const Operation = Io.Operation; -const Batch = Io.Batch; -const Terminal = Io.Terminal; -const LockedStderr = Io.LockedStderr; -const Clock = Io.Clock; -const Timestamp = Io.Timestamp; -const Duration = Io.Duration; +const Dir = Io.Dir; +const File = Io.File; +const Group = Io.Group; +const AnyFuture = Io.AnyFuture; +const ConcurrentError = Io.ConcurrentError; +const CancelProtection = Io.CancelProtection; +const Cancelable = Io.Cancelable; +const Timeout = Io.Timeout; +const Operation = Io.Operation; +const Batch = Io.Batch; +const Terminal = Io.Terminal; +const LockedStderr = Io.LockedStderr; +const Clock = Io.Clock; +const Timestamp = Io.Timestamp; +const Duration = Io.Duration; const RandomSecureError = Io.RandomSecureError; -const Queue = Io.Queue; -const Allocator = std.mem.Allocator; -const TaskID = Node.TaskID; +const Queue = Io.Queue; +const Allocator = std.mem.Allocator; +const TaskID = Node.TaskID; pub fn buildIOInterfaceForNode(node: *Node) Io { return .{ @@ -499,16 +499,16 @@ fn dirCreateDir(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, permissio node.createDir(parent, sub_path) catch |e| { return switch (e) { - Node.CreateDirError.InvalidHandle => unreachable, - Node.CreateDirError.ExistsAlready => Dir.CreateDirError.PathAlreadyExists, - Node.CreateDirError.EmptyPath => Dir.CreateDirError.BadPathName, - Node.CreateDirError.NoRootParent => Dir.CreateDirError.FileNotFound, - Node.CreateDirError.TooManyComponents => Dir.CreateDirError.NameTooLong, - Node.CreateDirError.ResolutionLimit => Dir.CreateDirError.NameTooLong, - Node.CreateDirError.ComponentNotDirectory => Dir.CreateDirError.NotDir, - Node.CreateDirError.ComponentNotFound => Dir.CreateDirError.FileNotFound, - Node.CreateDirError.OutOfMemory => Dir.CreateDirError.SystemResources, - Node.CreateDirError.Canceled => return error.Canceled, + Node.CreateDirError.InvalidHandle => unreachable, + Node.CreateDirError.ExistsAlready => Dir.CreateDirError.PathAlreadyExists, + Node.CreateDirError.EmptyPath => Dir.CreateDirError.BadPathName, + Node.CreateDirError.NoRootParent => Dir.CreateDirError.FileNotFound, + Node.CreateDirError.TooManyComponents => Dir.CreateDirError.NameTooLong, + Node.CreateDirError.ResolutionLimit => Dir.CreateDirError.NameTooLong, + Node.CreateDirError.ComponentNotDirectory => Dir.CreateDirError.NotDir, + Node.CreateDirError.ComponentNotFound => Dir.CreateDirError.FileNotFound, + Node.CreateDirError.OutOfMemory => Dir.CreateDirError.SystemResources, + Node.CreateDirError.Canceled => return error.Canceled, }; }; } @@ -538,17 +538,17 @@ fn dirOpenDir(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, options: Di const handle = node.openDir(parent, sub_path) catch |e| { return switch (e) { - Node.OpenDirError.InvalidHandle => unreachable, - Node.OpenDirError.DescriptorLimit => Dir.OpenError.ProcessFdQuotaExceeded, - Node.OpenDirError.IsDirectory => unreachable, - Node.OpenDirError.NotDirectory => Dir.OpenError.NotDir, - Node.OpenDirError.EmptyPath => Dir.OpenError.BadPathName, - Node.OpenDirError.NoRootParent => Dir.OpenError.FileNotFound, - Node.OpenDirError.TooManyComponents => Dir.OpenError.NameTooLong, - Node.OpenDirError.ResolutionLimit => Dir.OpenError.NameTooLong, - Node.OpenDirError.ComponentNotDirectory => Dir.OpenError.NotDir, - Node.OpenDirError.ComponentNotFound => Dir.OpenError.FileNotFound, - Node.OpenDirError.Canceled => return error.Canceled, + Node.OpenDirError.InvalidHandle => unreachable, + Node.OpenDirError.DescriptorLimit => Dir.OpenError.ProcessFdQuotaExceeded, + Node.OpenDirError.IsDirectory => unreachable, + Node.OpenDirError.NotDirectory => Dir.OpenError.NotDir, + Node.OpenDirError.EmptyPath => Dir.OpenError.BadPathName, + Node.OpenDirError.NoRootParent => Dir.OpenError.FileNotFound, + Node.OpenDirError.TooManyComponents => Dir.OpenError.NameTooLong, + Node.OpenDirError.ResolutionLimit => Dir.OpenError.NameTooLong, + Node.OpenDirError.ComponentNotDirectory => Dir.OpenError.NotDir, + Node.OpenDirError.ComponentNotFound => Dir.OpenError.FileNotFound, + Node.OpenDirError.Canceled => return error.Canceled, }; }; @@ -585,32 +585,32 @@ fn dirCreateFile(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, flags: D node.createFile(parent, sub_path) catch |e| { return switch (e) { - Node.CreateFileError.InvalidHandle => unreachable, - Node.CreateFileError.ExistsAlready => File.OpenError.PathAlreadyExists, - Node.CreateFileError.EmptyPath => File.OpenError.BadPathName, - Node.CreateFileError.NoRootParent => File.OpenError.FileNotFound, - Node.CreateFileError.TooManyComponents => File.OpenError.NameTooLong, - Node.CreateFileError.ResolutionLimit => File.OpenError.NameTooLong, - Node.CreateFileError.ComponentNotDirectory => File.OpenError.NotDir, - Node.CreateFileError.ComponentNotFound => File.OpenError.FileNotFound, - Node.CreateFileError.OutOfMemory => File.OpenError.SystemResources, - Node.CreateFileError.Canceled => return error.Canceled, + Node.CreateFileError.InvalidHandle => unreachable, + Node.CreateFileError.ExistsAlready => File.OpenError.PathAlreadyExists, + Node.CreateFileError.EmptyPath => File.OpenError.BadPathName, + Node.CreateFileError.NoRootParent => File.OpenError.FileNotFound, + Node.CreateFileError.TooManyComponents => File.OpenError.NameTooLong, + Node.CreateFileError.ResolutionLimit => File.OpenError.NameTooLong, + Node.CreateFileError.ComponentNotDirectory => File.OpenError.NotDir, + Node.CreateFileError.ComponentNotFound => File.OpenError.FileNotFound, + Node.CreateFileError.OutOfMemory => File.OpenError.SystemResources, + Node.CreateFileError.Canceled => return error.Canceled, }; }; const handle = node.openFile(parent, sub_path) catch |e| { return switch (e) { - Node.OpenFileError.InvalidHandle => unreachable, - Node.OpenFileError.DescriptorLimit => File.OpenError.ProcessFdQuotaExceeded, - Node.OpenFileError.IsDirectory => File.OpenError.IsDir, - Node.OpenFileError.NotDirectory => File.OpenError.NotDir, - Node.OpenFileError.EmptyPath => File.OpenError.BadPathName, - Node.OpenFileError.NoRootParent => File.OpenError.FileNotFound, - Node.OpenFileError.TooManyComponents => File.OpenError.NameTooLong, - Node.OpenFileError.ResolutionLimit => File.OpenError.NameTooLong, - Node.OpenFileError.ComponentNotDirectory => File.OpenError.NotDir, - Node.OpenFileError.ComponentNotFound => File.OpenError.FileNotFound, - Node.OpenFileError.Canceled => return error.Canceled, + Node.OpenFileError.InvalidHandle => unreachable, + Node.OpenFileError.DescriptorLimit => File.OpenError.ProcessFdQuotaExceeded, + Node.OpenFileError.IsDirectory => File.OpenError.IsDir, + Node.OpenFileError.NotDirectory => File.OpenError.NotDir, + Node.OpenFileError.EmptyPath => File.OpenError.BadPathName, + Node.OpenFileError.NoRootParent => File.OpenError.FileNotFound, + Node.OpenFileError.TooManyComponents => File.OpenError.NameTooLong, + Node.OpenFileError.ResolutionLimit => File.OpenError.NameTooLong, + Node.OpenFileError.ComponentNotDirectory => File.OpenError.NotDir, + Node.OpenFileError.ComponentNotFound => File.OpenError.FileNotFound, + Node.OpenFileError.Canceled => return error.Canceled, }; }; @@ -636,17 +636,17 @@ fn dirOpenFile(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, flags: Dir const handle = node.openFile(parent, sub_path) catch |e| { return switch (e) { - Node.OpenFileError.InvalidHandle => unreachable, - Node.OpenFileError.DescriptorLimit => File.OpenError.ProcessFdQuotaExceeded, - Node.OpenFileError.IsDirectory => File.OpenError.IsDir, - Node.OpenFileError.NotDirectory => File.OpenError.NotDir, - Node.OpenFileError.EmptyPath => File.OpenError.BadPathName, - Node.OpenFileError.NoRootParent => File.OpenError.FileNotFound, - Node.OpenFileError.TooManyComponents => File.OpenError.NameTooLong, - Node.OpenFileError.ResolutionLimit => File.OpenError.NameTooLong, - Node.OpenFileError.ComponentNotDirectory => File.OpenError.NotDir, - Node.OpenFileError.ComponentNotFound => File.OpenError.FileNotFound, - Node.OpenFileError.Canceled => return error.Canceled, + Node.OpenFileError.InvalidHandle => unreachable, + Node.OpenFileError.DescriptorLimit => File.OpenError.ProcessFdQuotaExceeded, + Node.OpenFileError.IsDirectory => File.OpenError.IsDir, + Node.OpenFileError.NotDirectory => File.OpenError.NotDir, + Node.OpenFileError.EmptyPath => File.OpenError.BadPathName, + Node.OpenFileError.NoRootParent => File.OpenError.FileNotFound, + Node.OpenFileError.TooManyComponents => File.OpenError.NameTooLong, + Node.OpenFileError.ResolutionLimit => File.OpenError.NameTooLong, + Node.OpenFileError.ComponentNotDirectory => File.OpenError.NotDir, + Node.OpenFileError.ComponentNotFound => File.OpenError.FileNotFound, + Node.OpenFileError.Canceled => return error.Canceled, }; }; @@ -745,17 +745,17 @@ fn dirDeleteDir(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8) Dir.Delet node.deleteDir(parent, sub_path) catch |e| { return switch (e) { - Node.DeleteDirError.InvalidHandle => unreachable, - Node.DeleteDirError.EmptyPath => Dir.DeleteDirError.BadPathName, - Node.DeleteDirError.NoRootParent => Dir.DeleteDirError.FileNotFound, - Node.DeleteDirError.TooManyComponents => Dir.DeleteDirError.NameTooLong, - Node.DeleteDirError.ResolutionLimit => Dir.DeleteDirError.NameTooLong, - Node.DeleteDirError.ComponentNotDirectory => Dir.DeleteDirError.NotDir, - Node.DeleteDirError.ComponentNotFound => Dir.DeleteDirError.FileNotFound, - Node.DeleteDirError.NotFound => Dir.DeleteDirError.FileNotFound, - Node.DeleteDirError.NotDirectory => Dir.DeleteDirError.NotDir, - Node.DeleteDirError.DirNotEmpty => Dir.DeleteDirError.DirNotEmpty, - Node.DeleteDirError.Canceled => return error.Canceled, + Node.DeleteDirError.InvalidHandle => unreachable, + Node.DeleteDirError.EmptyPath => Dir.DeleteDirError.BadPathName, + Node.DeleteDirError.NoRootParent => Dir.DeleteDirError.FileNotFound, + Node.DeleteDirError.TooManyComponents => Dir.DeleteDirError.NameTooLong, + Node.DeleteDirError.ResolutionLimit => Dir.DeleteDirError.NameTooLong, + Node.DeleteDirError.ComponentNotDirectory => Dir.DeleteDirError.NotDir, + Node.DeleteDirError.ComponentNotFound => Dir.DeleteDirError.FileNotFound, + Node.DeleteDirError.NotFound => Dir.DeleteDirError.FileNotFound, + Node.DeleteDirError.NotDirectory => Dir.DeleteDirError.NotDir, + Node.DeleteDirError.DirNotEmpty => Dir.DeleteDirError.DirNotEmpty, + Node.DeleteDirError.Canceled => return error.Canceled, }; }; } @@ -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 { diff --git a/src/node.zig b/src/node.zig index cda7177..4912c25 100644 --- a/src/node.zig +++ b/src/node.zig @@ -1,12 +1,12 @@ const std = @import("std"); const Allocator = std.mem.Allocator; -const FileSystem = @import("file_system.zig"); -const Network = @import("network.zig"); -const Scheduler = @import("scheduler.zig"); +const FileSystem = @import("file_system.zig"); +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); @@ -105,7 +98,7 @@ pub fn init( self.environ_map = try std.process.Environ.createMap(.empty, gpa); self.real_io = real_io; - self.stdin_reader = std.Io.File.stdin().readerStreaming(real_io, &.{}); + self.stdin_reader = std.Io.File.stdin().readerStreaming(real_io, &.{}); self.stdout_writer = std.Io.File.stdout().writerStreaming(real_io, &self.stdout_buffer); self.stderr_writer = std.Io.File.stderr().writerStreaming(real_io, &self.stderr_buffer); } @@ -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; diff --git a/src/scheduler.zig b/src/scheduler.zig index 86c6f0b..7dad856 100644 --- a/src/scheduler.zig +++ b/src/scheduler.zig @@ -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, @@ -133,14 +133,14 @@ fn spawnInner( .rip = @intFromPtr(&taskStart), .rdi = @intFromPtr(self), }, - .stack = stack, - .entry = entry, + .stack = stack, + .entry = entry, .context = context, - .state = .ready, + .state = .ready, .wakeup_time = null, .wakeup_tasks = null, .wakeup_futex = null, - .node = node, + .node = node, .parent_id = parent_id, .cancel = false, }; @@ -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; @@ -258,21 +259,21 @@ fn contextSwitch(old: *Registers, new: *Registers) void { : : [message] "{rsi}" (&ContextSwitch{ .old = old, .new = new }), : .{ - .rax = true, - .rcx = true, - .rdx = true, - .rbx = true, - .rsi = true, - .rdi = true, - .r8 = true, - .r9 = true, - .r10 = true, - .r11 = true, - .r12 = true, - .r13 = true, - .r14 = true, - .r15 = true, - .memory = true, + .rax = true, + .rcx = true, + .rdx = true, + .rbx = true, + .rsi = true, + .rdi = true, + .r8 = true, + .r9 = true, + .r10 = true, + .r11 = true, + .r12 = true, + .r13 = true, + .r14 = true, + .r15 = true, + .memory = true, }); } @@ -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(¤t.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(¤t.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(); }