node: add local_time and increment it by a fixed amount any time a task runs
This commit is contained in:
+84
-91
@@ -4,25 +4,25 @@ const Node = @import("node.zig");
|
|||||||
const Io = std.Io;
|
const Io = std.Io;
|
||||||
const net = Io.net;
|
const net = Io.net;
|
||||||
|
|
||||||
const Dir = Io.Dir;
|
const Dir = Io.Dir;
|
||||||
const File = Io.File;
|
const File = Io.File;
|
||||||
const Group = Io.Group;
|
const Group = Io.Group;
|
||||||
const AnyFuture = Io.AnyFuture;
|
const AnyFuture = Io.AnyFuture;
|
||||||
const ConcurrentError = Io.ConcurrentError;
|
const ConcurrentError = Io.ConcurrentError;
|
||||||
const CancelProtection = Io.CancelProtection;
|
const CancelProtection = Io.CancelProtection;
|
||||||
const Cancelable = Io.Cancelable;
|
const Cancelable = Io.Cancelable;
|
||||||
const Timeout = Io.Timeout;
|
const Timeout = Io.Timeout;
|
||||||
const Operation = Io.Operation;
|
const Operation = Io.Operation;
|
||||||
const Batch = Io.Batch;
|
const Batch = Io.Batch;
|
||||||
const Terminal = Io.Terminal;
|
const Terminal = Io.Terminal;
|
||||||
const LockedStderr = Io.LockedStderr;
|
const LockedStderr = Io.LockedStderr;
|
||||||
const Clock = Io.Clock;
|
const Clock = Io.Clock;
|
||||||
const Timestamp = Io.Timestamp;
|
const Timestamp = Io.Timestamp;
|
||||||
const Duration = Io.Duration;
|
const Duration = Io.Duration;
|
||||||
const RandomSecureError = Io.RandomSecureError;
|
const RandomSecureError = Io.RandomSecureError;
|
||||||
const Queue = Io.Queue;
|
const Queue = Io.Queue;
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const TaskID = Node.TaskID;
|
const TaskID = Node.TaskID;
|
||||||
|
|
||||||
pub fn buildIOInterfaceForNode(node: *Node) Io {
|
pub fn buildIOInterfaceForNode(node: *Node) Io {
|
||||||
return .{
|
return .{
|
||||||
@@ -499,16 +499,16 @@ fn dirCreateDir(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, permissio
|
|||||||
|
|
||||||
node.createDir(parent, sub_path) catch |e| {
|
node.createDir(parent, sub_path) catch |e| {
|
||||||
return switch (e) {
|
return switch (e) {
|
||||||
Node.CreateDirError.InvalidHandle => unreachable,
|
Node.CreateDirError.InvalidHandle => unreachable,
|
||||||
Node.CreateDirError.ExistsAlready => Dir.CreateDirError.PathAlreadyExists,
|
Node.CreateDirError.ExistsAlready => Dir.CreateDirError.PathAlreadyExists,
|
||||||
Node.CreateDirError.EmptyPath => Dir.CreateDirError.BadPathName,
|
Node.CreateDirError.EmptyPath => Dir.CreateDirError.BadPathName,
|
||||||
Node.CreateDirError.NoRootParent => Dir.CreateDirError.FileNotFound,
|
Node.CreateDirError.NoRootParent => Dir.CreateDirError.FileNotFound,
|
||||||
Node.CreateDirError.TooManyComponents => Dir.CreateDirError.NameTooLong,
|
Node.CreateDirError.TooManyComponents => Dir.CreateDirError.NameTooLong,
|
||||||
Node.CreateDirError.ResolutionLimit => Dir.CreateDirError.NameTooLong,
|
Node.CreateDirError.ResolutionLimit => Dir.CreateDirError.NameTooLong,
|
||||||
Node.CreateDirError.ComponentNotDirectory => Dir.CreateDirError.NotDir,
|
Node.CreateDirError.ComponentNotDirectory => Dir.CreateDirError.NotDir,
|
||||||
Node.CreateDirError.ComponentNotFound => Dir.CreateDirError.FileNotFound,
|
Node.CreateDirError.ComponentNotFound => Dir.CreateDirError.FileNotFound,
|
||||||
Node.CreateDirError.OutOfMemory => Dir.CreateDirError.SystemResources,
|
Node.CreateDirError.OutOfMemory => Dir.CreateDirError.SystemResources,
|
||||||
Node.CreateDirError.Canceled => return error.Canceled,
|
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| {
|
const handle = node.openDir(parent, sub_path) catch |e| {
|
||||||
return switch (e) {
|
return switch (e) {
|
||||||
Node.OpenDirError.InvalidHandle => unreachable,
|
Node.OpenDirError.InvalidHandle => unreachable,
|
||||||
Node.OpenDirError.DescriptorLimit => Dir.OpenError.ProcessFdQuotaExceeded,
|
Node.OpenDirError.DescriptorLimit => Dir.OpenError.ProcessFdQuotaExceeded,
|
||||||
Node.OpenDirError.IsDirectory => unreachable,
|
Node.OpenDirError.IsDirectory => unreachable,
|
||||||
Node.OpenDirError.NotDirectory => Dir.OpenError.NotDir,
|
Node.OpenDirError.NotDirectory => Dir.OpenError.NotDir,
|
||||||
Node.OpenDirError.EmptyPath => Dir.OpenError.BadPathName,
|
Node.OpenDirError.EmptyPath => Dir.OpenError.BadPathName,
|
||||||
Node.OpenDirError.NoRootParent => Dir.OpenError.FileNotFound,
|
Node.OpenDirError.NoRootParent => Dir.OpenError.FileNotFound,
|
||||||
Node.OpenDirError.TooManyComponents => Dir.OpenError.NameTooLong,
|
Node.OpenDirError.TooManyComponents => Dir.OpenError.NameTooLong,
|
||||||
Node.OpenDirError.ResolutionLimit => Dir.OpenError.NameTooLong,
|
Node.OpenDirError.ResolutionLimit => Dir.OpenError.NameTooLong,
|
||||||
Node.OpenDirError.ComponentNotDirectory => Dir.OpenError.NotDir,
|
Node.OpenDirError.ComponentNotDirectory => Dir.OpenError.NotDir,
|
||||||
Node.OpenDirError.ComponentNotFound => Dir.OpenError.FileNotFound,
|
Node.OpenDirError.ComponentNotFound => Dir.OpenError.FileNotFound,
|
||||||
Node.OpenDirError.Canceled => return error.Canceled,
|
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| {
|
node.createFile(parent, sub_path) catch |e| {
|
||||||
return switch (e) {
|
return switch (e) {
|
||||||
Node.CreateFileError.InvalidHandle => unreachable,
|
Node.CreateFileError.InvalidHandle => unreachable,
|
||||||
Node.CreateFileError.ExistsAlready => File.OpenError.PathAlreadyExists,
|
Node.CreateFileError.ExistsAlready => File.OpenError.PathAlreadyExists,
|
||||||
Node.CreateFileError.EmptyPath => File.OpenError.BadPathName,
|
Node.CreateFileError.EmptyPath => File.OpenError.BadPathName,
|
||||||
Node.CreateFileError.NoRootParent => File.OpenError.FileNotFound,
|
Node.CreateFileError.NoRootParent => File.OpenError.FileNotFound,
|
||||||
Node.CreateFileError.TooManyComponents => File.OpenError.NameTooLong,
|
Node.CreateFileError.TooManyComponents => File.OpenError.NameTooLong,
|
||||||
Node.CreateFileError.ResolutionLimit => File.OpenError.NameTooLong,
|
Node.CreateFileError.ResolutionLimit => File.OpenError.NameTooLong,
|
||||||
Node.CreateFileError.ComponentNotDirectory => File.OpenError.NotDir,
|
Node.CreateFileError.ComponentNotDirectory => File.OpenError.NotDir,
|
||||||
Node.CreateFileError.ComponentNotFound => File.OpenError.FileNotFound,
|
Node.CreateFileError.ComponentNotFound => File.OpenError.FileNotFound,
|
||||||
Node.CreateFileError.OutOfMemory => File.OpenError.SystemResources,
|
Node.CreateFileError.OutOfMemory => File.OpenError.SystemResources,
|
||||||
Node.CreateFileError.Canceled => return error.Canceled,
|
Node.CreateFileError.Canceled => return error.Canceled,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const handle = node.openFile(parent, sub_path) catch |e| {
|
const handle = node.openFile(parent, sub_path) catch |e| {
|
||||||
return switch (e) {
|
return switch (e) {
|
||||||
Node.OpenFileError.InvalidHandle => unreachable,
|
Node.OpenFileError.InvalidHandle => unreachable,
|
||||||
Node.OpenFileError.DescriptorLimit => File.OpenError.ProcessFdQuotaExceeded,
|
Node.OpenFileError.DescriptorLimit => File.OpenError.ProcessFdQuotaExceeded,
|
||||||
Node.OpenFileError.IsDirectory => File.OpenError.IsDir,
|
Node.OpenFileError.IsDirectory => File.OpenError.IsDir,
|
||||||
Node.OpenFileError.NotDirectory => File.OpenError.NotDir,
|
Node.OpenFileError.NotDirectory => File.OpenError.NotDir,
|
||||||
Node.OpenFileError.EmptyPath => File.OpenError.BadPathName,
|
Node.OpenFileError.EmptyPath => File.OpenError.BadPathName,
|
||||||
Node.OpenFileError.NoRootParent => File.OpenError.FileNotFound,
|
Node.OpenFileError.NoRootParent => File.OpenError.FileNotFound,
|
||||||
Node.OpenFileError.TooManyComponents => File.OpenError.NameTooLong,
|
Node.OpenFileError.TooManyComponents => File.OpenError.NameTooLong,
|
||||||
Node.OpenFileError.ResolutionLimit => File.OpenError.NameTooLong,
|
Node.OpenFileError.ResolutionLimit => File.OpenError.NameTooLong,
|
||||||
Node.OpenFileError.ComponentNotDirectory => File.OpenError.NotDir,
|
Node.OpenFileError.ComponentNotDirectory => File.OpenError.NotDir,
|
||||||
Node.OpenFileError.ComponentNotFound => File.OpenError.FileNotFound,
|
Node.OpenFileError.ComponentNotFound => File.OpenError.FileNotFound,
|
||||||
Node.OpenFileError.Canceled => return error.Canceled,
|
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| {
|
const handle = node.openFile(parent, sub_path) catch |e| {
|
||||||
return switch (e) {
|
return switch (e) {
|
||||||
Node.OpenFileError.InvalidHandle => unreachable,
|
Node.OpenFileError.InvalidHandle => unreachable,
|
||||||
Node.OpenFileError.DescriptorLimit => File.OpenError.ProcessFdQuotaExceeded,
|
Node.OpenFileError.DescriptorLimit => File.OpenError.ProcessFdQuotaExceeded,
|
||||||
Node.OpenFileError.IsDirectory => File.OpenError.IsDir,
|
Node.OpenFileError.IsDirectory => File.OpenError.IsDir,
|
||||||
Node.OpenFileError.NotDirectory => File.OpenError.NotDir,
|
Node.OpenFileError.NotDirectory => File.OpenError.NotDir,
|
||||||
Node.OpenFileError.EmptyPath => File.OpenError.BadPathName,
|
Node.OpenFileError.EmptyPath => File.OpenError.BadPathName,
|
||||||
Node.OpenFileError.NoRootParent => File.OpenError.FileNotFound,
|
Node.OpenFileError.NoRootParent => File.OpenError.FileNotFound,
|
||||||
Node.OpenFileError.TooManyComponents => File.OpenError.NameTooLong,
|
Node.OpenFileError.TooManyComponents => File.OpenError.NameTooLong,
|
||||||
Node.OpenFileError.ResolutionLimit => File.OpenError.NameTooLong,
|
Node.OpenFileError.ResolutionLimit => File.OpenError.NameTooLong,
|
||||||
Node.OpenFileError.ComponentNotDirectory => File.OpenError.NotDir,
|
Node.OpenFileError.ComponentNotDirectory => File.OpenError.NotDir,
|
||||||
Node.OpenFileError.ComponentNotFound => File.OpenError.FileNotFound,
|
Node.OpenFileError.ComponentNotFound => File.OpenError.FileNotFound,
|
||||||
Node.OpenFileError.Canceled => return error.Canceled,
|
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| {
|
node.deleteDir(parent, sub_path) catch |e| {
|
||||||
return switch (e) {
|
return switch (e) {
|
||||||
Node.DeleteDirError.InvalidHandle => unreachable,
|
Node.DeleteDirError.InvalidHandle => unreachable,
|
||||||
Node.DeleteDirError.EmptyPath => Dir.DeleteDirError.BadPathName,
|
Node.DeleteDirError.EmptyPath => Dir.DeleteDirError.BadPathName,
|
||||||
Node.DeleteDirError.NoRootParent => Dir.DeleteDirError.FileNotFound,
|
Node.DeleteDirError.NoRootParent => Dir.DeleteDirError.FileNotFound,
|
||||||
Node.DeleteDirError.TooManyComponents => Dir.DeleteDirError.NameTooLong,
|
Node.DeleteDirError.TooManyComponents => Dir.DeleteDirError.NameTooLong,
|
||||||
Node.DeleteDirError.ResolutionLimit => Dir.DeleteDirError.NameTooLong,
|
Node.DeleteDirError.ResolutionLimit => Dir.DeleteDirError.NameTooLong,
|
||||||
Node.DeleteDirError.ComponentNotDirectory => Dir.DeleteDirError.NotDir,
|
Node.DeleteDirError.ComponentNotDirectory => Dir.DeleteDirError.NotDir,
|
||||||
Node.DeleteDirError.ComponentNotFound => Dir.DeleteDirError.FileNotFound,
|
Node.DeleteDirError.ComponentNotFound => Dir.DeleteDirError.FileNotFound,
|
||||||
Node.DeleteDirError.NotFound => Dir.DeleteDirError.FileNotFound,
|
Node.DeleteDirError.NotFound => Dir.DeleteDirError.FileNotFound,
|
||||||
Node.DeleteDirError.NotDirectory => Dir.DeleteDirError.NotDir,
|
Node.DeleteDirError.NotDirectory => Dir.DeleteDirError.NotDir,
|
||||||
Node.DeleteDirError.DirNotEmpty => Dir.DeleteDirError.DirNotEmpty,
|
Node.DeleteDirError.DirNotEmpty => Dir.DeleteDirError.DirNotEmpty,
|
||||||
Node.DeleteDirError.Canceled => return error.Canceled,
|
Node.DeleteDirError.Canceled => return error.Canceled,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -868,14 +868,7 @@ fn fileClose(userdata: ?*anyopaque, files: []const File) void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fileWritePositional(
|
fn fileWritePositional(userdata: ?*anyopaque, file: File, header: []const u8, data: []const []const u8, splat: usize, offset: u64) File.WritePositionalError!usize {
|
||||||
userdata: ?*anyopaque,
|
|
||||||
file : File,
|
|
||||||
header : []const u8,
|
|
||||||
data : []const []const u8,
|
|
||||||
splat : usize,
|
|
||||||
offset : u64
|
|
||||||
) File.WritePositionalError!usize {
|
|
||||||
const node: *Node = @ptrCast(@alignCast(userdata.?));
|
const node: *Node = @ptrCast(@alignCast(userdata.?));
|
||||||
var cursor = std.math.cast(usize, offset) orelse return File.WritePositionalError.FileTooBig;
|
var cursor = std.math.cast(usize, offset) orelse return File.WritePositionalError.FileTooBig;
|
||||||
var copied: usize = 0;
|
var copied: usize = 0;
|
||||||
@@ -1201,7 +1194,7 @@ fn now(userdata: ?*anyopaque, clock: Clock) Timestamp {
|
|||||||
// TODO: Return an appropriate time for each clock
|
// TODO: Return an appropriate time for each clock
|
||||||
_ = clock;
|
_ = clock;
|
||||||
|
|
||||||
return .{ .nanoseconds = node.scheduler.current_time * 1000 };
|
return .{ .nanoseconds = node.local_time * 1000 };
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clockResolution(userdata: ?*anyopaque, clock: Clock) Clock.ResolutionError!Duration {
|
fn clockResolution(userdata: ?*anyopaque, clock: Clock) Clock.ResolutionError!Duration {
|
||||||
|
|||||||
+25
-55
@@ -1,12 +1,12 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
const FileSystem = @import("file_system.zig");
|
const FileSystem = @import("file_system.zig");
|
||||||
const Network = @import("network.zig");
|
const Network = @import("network.zig");
|
||||||
const Scheduler = @import("scheduler.zig");
|
const Scheduler = @import("scheduler.zig");
|
||||||
const ioInterface = @import("io_interface.zig");
|
const ioInterface = @import("io_interface.zig");
|
||||||
|
|
||||||
const MAX_DESCRIPTORS = 1<<10;
|
const MAX_DESCRIPTORS = 1 << 10;
|
||||||
|
|
||||||
const Node = @This();
|
const Node = @This();
|
||||||
const Handle = i32;
|
const Handle = i32;
|
||||||
@@ -15,7 +15,6 @@ pub const TaskID = Scheduler.TaskID;
|
|||||||
const NestedEntryPoint = Scheduler.NestedEntryPoint;
|
const NestedEntryPoint = Scheduler.NestedEntryPoint;
|
||||||
|
|
||||||
const Descriptor = struct {
|
const Descriptor = struct {
|
||||||
|
|
||||||
const Kind = enum {
|
const Kind = enum {
|
||||||
dir,
|
dir,
|
||||||
file,
|
file,
|
||||||
@@ -24,14 +23,15 @@ const Descriptor = struct {
|
|||||||
unused,
|
unused,
|
||||||
};
|
};
|
||||||
|
|
||||||
kind : Kind = .unused,
|
kind: Kind = .unused,
|
||||||
dir : FileSystem.OpenDir = undefined,
|
dir: FileSystem.OpenDir = undefined,
|
||||||
file : FileSystem.OpenFile = undefined,
|
file: FileSystem.OpenFile = undefined,
|
||||||
listen: Network.ListenSocket = undefined,
|
listen: Network.ListenSocket = undefined,
|
||||||
conn : Network.ConnSocket = undefined,
|
conn: Network.ConnSocket = undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
gpa: Allocator,
|
gpa: Allocator,
|
||||||
|
local_time: u64,
|
||||||
arena: std.heap.ArenaAllocator,
|
arena: std.heap.ArenaAllocator,
|
||||||
argv: [][*:0]const u8,
|
argv: [][*:0]const u8,
|
||||||
environ_map: std.process.Environ.Map,
|
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
|
// Count how many arguments there are
|
||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
while (cursor < command.len) {
|
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;
|
count += 1;
|
||||||
cursor += 1;
|
cursor += 1;
|
||||||
}
|
}
|
||||||
@@ -80,16 +80,9 @@ fn splitCommandArguments(command: []const u8, arena: Allocator) Allocator.Error!
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(
|
pub fn init(self: *Node, real_io: std.Io, scheduler: *Scheduler, network: *Network, command: []const u8, addresses: []const u32, gpa: Allocator) !void {
|
||||||
self : *Node,
|
|
||||||
real_io : std.Io,
|
|
||||||
scheduler: *Scheduler,
|
|
||||||
network : *Network,
|
|
||||||
command : []const u8,
|
|
||||||
addresses: []const u32,
|
|
||||||
gpa : Allocator
|
|
||||||
) !void {
|
|
||||||
self.gpa = gpa;
|
self.gpa = gpa;
|
||||||
|
self.local_time = 0;
|
||||||
self.arena = .init(gpa);
|
self.arena = .init(gpa);
|
||||||
self.scheduler = scheduler;
|
self.scheduler = scheduler;
|
||||||
try self.file_system.init(gpa);
|
try self.file_system.init(gpa);
|
||||||
@@ -105,7 +98,7 @@ pub fn init(
|
|||||||
self.environ_map = try std.process.Environ.createMap(.empty, gpa);
|
self.environ_map = try std.process.Environ.createMap(.empty, gpa);
|
||||||
|
|
||||||
self.real_io = real_io;
|
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.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);
|
self.stderr_writer = std.Io.File.stderr().writerStreaming(real_io, &self.stderr_buffer);
|
||||||
}
|
}
|
||||||
@@ -183,11 +176,11 @@ fn unusedDesc(self: *Node) ?*Descriptor {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const HandleError = error {
|
const HandleError = error{
|
||||||
InvalidHandle,
|
InvalidHandle,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const CancelError = error {
|
pub const CancelError = error{
|
||||||
Canceled,
|
Canceled,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -237,14 +230,10 @@ pub const CreateDirError = HandleError || FileSystem.CreateError || CancelError;
|
|||||||
|
|
||||||
pub fn createDir(self: *Node, parent: ?Handle, path: []const u8) CreateDirError!void {
|
pub fn createDir(self: *Node, parent: ?Handle, path: []const u8) CreateDirError!void {
|
||||||
try self.scheduler.sleep(10);
|
try self.scheduler.sleep(10);
|
||||||
return self.file_system.createDir(
|
return self.file_system.createDir(path, try self.handleToOpenDirOrNULL(parent), self.gpa);
|
||||||
path,
|
|
||||||
try self.handleToOpenDirOrNULL(parent),
|
|
||||||
self.gpa
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const OpenDirError = error {
|
pub const OpenDirError = error{
|
||||||
DescriptorLimit,
|
DescriptorLimit,
|
||||||
} || HandleError || FileSystem.OpenError || CancelError;
|
} || 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 {
|
pub fn createFile(self: *Node, parent: ?Handle, path: []const u8) CreateFileError!void {
|
||||||
try self.scheduler.sleep(10);
|
try self.scheduler.sleep(10);
|
||||||
return self.file_system.createFile(
|
return self.file_system.createFile(path, try self.handleToOpenDirOrNULL(parent), self.gpa);
|
||||||
path,
|
|
||||||
try self.handleToOpenDirOrNULL(parent),
|
|
||||||
self.gpa
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const DeleteFileError = HandleError || FileSystem.DeleteFileError || CancelError;
|
pub const DeleteFileError = HandleError || FileSystem.DeleteFileError || CancelError;
|
||||||
|
|
||||||
pub fn deleteFile(self: *Node, parent: ?Handle, path: []const u8) DeleteFileError!void {
|
pub fn deleteFile(self: *Node, parent: ?Handle, path: []const u8) DeleteFileError!void {
|
||||||
try self.scheduler.sleep(10);
|
try self.scheduler.sleep(10);
|
||||||
return self.file_system.deleteFile(
|
return self.file_system.deleteFile(path, try self.handleToOpenDirOrNULL(parent), self.gpa);
|
||||||
path,
|
|
||||||
try self.handleToOpenDirOrNULL(parent),
|
|
||||||
self.gpa
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const DeleteDirError = HandleError || FileSystem.DeleteDirError || CancelError;
|
pub const DeleteDirError = HandleError || FileSystem.DeleteDirError || CancelError;
|
||||||
|
|
||||||
pub fn deleteDir(self: *Node, parent: ?Handle, path: []const u8) DeleteDirError!void {
|
pub fn deleteDir(self: *Node, parent: ?Handle, path: []const u8) DeleteDirError!void {
|
||||||
try self.scheduler.sleep(10);
|
try self.scheduler.sleep(10);
|
||||||
return self.file_system.deleteDir(
|
return self.file_system.deleteDir(path, try self.handleToOpenDirOrNULL(parent), self.gpa);
|
||||||
path,
|
|
||||||
try self.handleToOpenDirOrNULL(parent),
|
|
||||||
self.gpa
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const OpenFileError = error {
|
pub const OpenFileError = error{
|
||||||
DescriptorLimit,
|
DescriptorLimit,
|
||||||
} || HandleError || FileSystem.OpenError || CancelError;
|
} || HandleError || FileSystem.OpenError || CancelError;
|
||||||
|
|
||||||
@@ -383,14 +360,7 @@ fn writeToStderr(self: *Node, source: []const u8) void {
|
|||||||
|
|
||||||
pub const WriteFileError = HandleError || Allocator.Error || CancelError;
|
pub const WriteFileError = HandleError || Allocator.Error || CancelError;
|
||||||
|
|
||||||
pub fn writeFile(
|
pub fn writeFile(self: *Node, handle: Handle, offset: ?usize, header: []const u8, source: []const []const u8) WriteFileError!usize {
|
||||||
self : *Node,
|
|
||||||
handle: Handle,
|
|
||||||
offset: ?usize,
|
|
||||||
header: []const u8,
|
|
||||||
source: []const []const u8
|
|
||||||
) WriteFileError!usize {
|
|
||||||
|
|
||||||
try self.scheduler.sleep(100);
|
try self.scheduler.sleep(100);
|
||||||
|
|
||||||
if (handle == 0) {
|
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 Address = Network.Address;
|
||||||
pub const ListenError = error {
|
pub const ListenError = error{
|
||||||
DescriptorLimit,
|
DescriptorLimit,
|
||||||
} || Network.ListenError || CancelError;
|
} || Network.ListenError || CancelError;
|
||||||
|
|
||||||
@@ -453,7 +423,7 @@ pub fn listen(self: *Node, address: Address) ListenError!Handle {
|
|||||||
return self.descToHandle(desc);
|
return self.descToHandle(desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const AcceptError = error {
|
pub const AcceptError = error{
|
||||||
DescriptorLimit,
|
DescriptorLimit,
|
||||||
} || HandleError || Network.AcceptError || CancelError;
|
} || 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,
|
DescriptorLimit,
|
||||||
} || Network.ConnectError || CancelError;
|
} || Network.ConnectError || CancelError;
|
||||||
|
|
||||||
|
|||||||
+37
-32
@@ -4,8 +4,8 @@ const Node = @import("node.zig");
|
|||||||
|
|
||||||
const Scheduler = @This();
|
const Scheduler = @This();
|
||||||
|
|
||||||
pub const MainEntryPoint = *const fn(std.process.Init) anyerror!void;
|
pub const MainEntryPoint = *const fn (std.process.Init) anyerror!void;
|
||||||
pub const NestedEntryPoint = *const fn(context: *const anyopaque) void;
|
pub const NestedEntryPoint = *const fn (context: *const anyopaque) void;
|
||||||
|
|
||||||
pub const EntryPoint = union(enum) {
|
pub const EntryPoint = union(enum) {
|
||||||
main: MainEntryPoint,
|
main: MainEntryPoint,
|
||||||
@@ -26,6 +26,7 @@ const ContextSwitch = extern struct {
|
|||||||
|
|
||||||
const STACK_CANARY_SIZE = 256;
|
const STACK_CANARY_SIZE = 256;
|
||||||
const STACK_CANARY_BYTE = 0xa5;
|
const STACK_CANARY_BYTE = 0xa5;
|
||||||
|
const TASK_RUN_COST_US = 50;
|
||||||
|
|
||||||
pub const TaskID = u64;
|
pub const TaskID = u64;
|
||||||
|
|
||||||
@@ -38,13 +39,13 @@ const State = enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const Task = struct {
|
const Task = struct {
|
||||||
id : TaskID,
|
id: TaskID,
|
||||||
regs : Registers,
|
regs: Registers,
|
||||||
stack : []align(16) u8,
|
stack: []align(16) u8,
|
||||||
entry : EntryPoint,
|
entry: EntryPoint,
|
||||||
context: ?*const anyopaque,
|
context: ?*const anyopaque,
|
||||||
state : State,
|
state: State,
|
||||||
node : *Node,
|
node: *Node,
|
||||||
|
|
||||||
// If this is a subtask, parent_id refers to the parent.
|
// If this is a subtask, parent_id refers to the parent.
|
||||||
// The cancel flag is set when the parent requests cancellation.
|
// The cancel flag is set when the parent requests cancellation.
|
||||||
@@ -107,7 +108,6 @@ fn spawnInner(
|
|||||||
parent_id: ?TaskID,
|
parent_id: ?TaskID,
|
||||||
context: ?*const anyopaque,
|
context: ?*const anyopaque,
|
||||||
) !*Task {
|
) !*Task {
|
||||||
|
|
||||||
if (stack_size > std.math.maxInt(usize) - STACK_CANARY_SIZE)
|
if (stack_size > std.math.maxInt(usize) - STACK_CANARY_SIZE)
|
||||||
return Allocator.Error.OutOfMemory;
|
return Allocator.Error.OutOfMemory;
|
||||||
|
|
||||||
@@ -125,7 +125,7 @@ fn spawnInner(
|
|||||||
const id = self.next_task_id;
|
const id = self.next_task_id;
|
||||||
defer self.next_task_id += 1;
|
defer self.next_task_id += 1;
|
||||||
|
|
||||||
const task = Task {
|
const task = Task{
|
||||||
.id = id,
|
.id = id,
|
||||||
.regs = .{
|
.regs = .{
|
||||||
.rsp = stack_top,
|
.rsp = stack_top,
|
||||||
@@ -133,14 +133,14 @@ fn spawnInner(
|
|||||||
.rip = @intFromPtr(&taskStart),
|
.rip = @intFromPtr(&taskStart),
|
||||||
.rdi = @intFromPtr(self),
|
.rdi = @intFromPtr(self),
|
||||||
},
|
},
|
||||||
.stack = stack,
|
.stack = stack,
|
||||||
.entry = entry,
|
.entry = entry,
|
||||||
.context = context,
|
.context = context,
|
||||||
.state = .ready,
|
.state = .ready,
|
||||||
.wakeup_time = null,
|
.wakeup_time = null,
|
||||||
.wakeup_tasks = null,
|
.wakeup_tasks = null,
|
||||||
.wakeup_futex = null,
|
.wakeup_futex = null,
|
||||||
.node = node,
|
.node = node,
|
||||||
.parent_id = parent_id,
|
.parent_id = parent_id,
|
||||||
.cancel = false,
|
.cancel = false,
|
||||||
};
|
};
|
||||||
@@ -196,6 +196,9 @@ fn findBlockedTaskWithLowestWakeupTime(self: *Scheduler) ?*Task {
|
|||||||
fn advanceTimeAndUnblockTasks(self: *Scheduler, new_time: u64) void {
|
fn advanceTimeAndUnblockTasks(self: *Scheduler, new_time: u64) void {
|
||||||
std.debug.assert(self.current_time < new_time);
|
std.debug.assert(self.current_time < new_time);
|
||||||
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| {
|
for (self.tasks.items) |*task| {
|
||||||
if (task.state == .blocked) {
|
if (task.state == .blocked) {
|
||||||
if (task.wakeup_time) |wakeup_time| {
|
if (task.wakeup_time) |wakeup_time| {
|
||||||
@@ -229,9 +232,7 @@ fn advanceTimeAndPickTask(self: *Scheduler) ?*Task {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn scheduleOne(self: *Scheduler) bool {
|
pub fn scheduleOne(self: *Scheduler) bool {
|
||||||
const task = self.findTaskWithState(.ready)
|
const task = self.findTaskWithState(.ready) orelse self.advanceTimeAndPickTask() orelse return false;
|
||||||
orelse self.advanceTimeAndPickTask()
|
|
||||||
orelse return false;
|
|
||||||
const id = task.id;
|
const id = task.id;
|
||||||
self.current_id = id;
|
self.current_id = id;
|
||||||
task.state = .running;
|
task.state = .running;
|
||||||
@@ -258,21 +259,21 @@ fn contextSwitch(old: *Registers, new: *Registers) void {
|
|||||||
:
|
:
|
||||||
: [message] "{rsi}" (&ContextSwitch{ .old = old, .new = new }),
|
: [message] "{rsi}" (&ContextSwitch{ .old = old, .new = new }),
|
||||||
: .{
|
: .{
|
||||||
.rax = true,
|
.rax = true,
|
||||||
.rcx = true,
|
.rcx = true,
|
||||||
.rdx = true,
|
.rdx = true,
|
||||||
.rbx = true,
|
.rbx = true,
|
||||||
.rsi = true,
|
.rsi = true,
|
||||||
.rdi = true,
|
.rdi = true,
|
||||||
.r8 = true,
|
.r8 = true,
|
||||||
.r9 = true,
|
.r9 = true,
|
||||||
.r10 = true,
|
.r10 = true,
|
||||||
.r11 = true,
|
.r11 = true,
|
||||||
.r12 = true,
|
.r12 = true,
|
||||||
.r13 = true,
|
.r13 = true,
|
||||||
.r14 = true,
|
.r14 = true,
|
||||||
.r15 = true,
|
.r15 = true,
|
||||||
.memory = true,
|
.memory = true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,6 +297,7 @@ fn taskStart(self: *Scheduler) callconv(.c) noreturn {
|
|||||||
current.wakeup_time = null;
|
current.wakeup_time = null;
|
||||||
current.wakeup_tasks = null;
|
current.wakeup_tasks = null;
|
||||||
current.wakeup_futex = null;
|
current.wakeup_futex = null;
|
||||||
|
current.node.local_time += TASK_RUN_COST_US;
|
||||||
if (current.parent_id) |parent_id| {
|
if (current.parent_id) |parent_id| {
|
||||||
if (self.findTaskByID(parent_id)) |parent| {
|
if (self.findTaskByID(parent_id)) |parent| {
|
||||||
if (taskIsWaitingFor(parent, current.id)) {
|
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_time = self.current_time + delta_us;
|
||||||
current.wakeup_tasks = null;
|
current.wakeup_tasks = null;
|
||||||
current.wakeup_futex = null;
|
current.wakeup_futex = null;
|
||||||
|
current.node.local_time += TASK_RUN_COST_US;
|
||||||
contextSwitch(¤t.regs, &self.regs);
|
contextSwitch(¤t.regs, &self.regs);
|
||||||
try self.checkCancel();
|
try self.checkCancel();
|
||||||
}
|
}
|
||||||
@@ -341,6 +344,7 @@ pub fn futexWaitUncancelable(self: *Scheduler, ptr: *const u32, expected: u32) v
|
|||||||
current.wakeup_time = null;
|
current.wakeup_time = null;
|
||||||
current.wakeup_tasks = null;
|
current.wakeup_tasks = null;
|
||||||
current.wakeup_futex = ptr;
|
current.wakeup_futex = ptr;
|
||||||
|
current.node.local_time += TASK_RUN_COST_US;
|
||||||
contextSwitch(¤t.regs, &self.regs);
|
contextSwitch(¤t.regs, &self.regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -385,6 +389,7 @@ pub fn wait(self: *Scheduler, ids: []const TaskID) !TaskID {
|
|||||||
task.wakeup_time = null;
|
task.wakeup_time = null;
|
||||||
task.wakeup_tasks = ids;
|
task.wakeup_tasks = ids;
|
||||||
task.wakeup_futex = null;
|
task.wakeup_futex = null;
|
||||||
|
task.node.local_time += TASK_RUN_COST_US;
|
||||||
contextSwitch(&task.regs, &self.regs);
|
contextSwitch(&task.regs, &self.regs);
|
||||||
try self.checkCancel();
|
try self.checkCancel();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user