core+system: Add a bunch of syscalls related to thread creation
This commit is contained in:
parent
30c0f23ff0
commit
e52b0bcf77
@ -40,7 +40,7 @@ pub fn lockFrame(_: *platform.Registers, args: *sys.Arguments, _: *isize) anyerr
|
|||||||
|
|
||||||
pub fn setAddressSpace(_: *platform.Registers, args: *sys.Arguments, _: *isize) anyerror!void {
|
pub fn setAddressSpace(_: *platform.Registers, args: *sys.Arguments, _: *isize) anyerror!void {
|
||||||
const core = cpu.thisCore();
|
const core = cpu.thisCore();
|
||||||
if (!sys.checkToken(core, system.kernel.Token.VirtualMemory)) return error.NotAuthorized;
|
if (!sys.checkToken(core, system.kernel.Token.CreateProcess)) return error.NotAuthorized;
|
||||||
|
|
||||||
const target = thread.lookupThreadById(args.arg0) orelse return error.NoSuchThread;
|
const target = thread.lookupThreadById(args.arg0) orelse return error.NoSuchThread;
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ pub fn sleep(regs: *platform.Registers, args: *sys.Arguments, _: *isize) anyerro
|
|||||||
|
|
||||||
pub fn setEventQueue(_: *platform.Registers, args: *sys.Arguments, _: *isize) anyerror!void {
|
pub fn setEventQueue(_: *platform.Registers, args: *sys.Arguments, _: *isize) anyerror!void {
|
||||||
const core = cpu.thisCore();
|
const core = cpu.thisCore();
|
||||||
if (!sys.checkToken(core, system.kernel.Token.EventQueue)) return error.NotAuthorized;
|
if (!sys.checkToken(core, system.kernel.Token.CreateProcess)) return error.NotAuthorized;
|
||||||
const target = thread.lookupThreadById(args.arg0) orelse return error.NoSuchThread;
|
const target = thread.lookupThreadById(args.arg0) orelse return error.NoSuchThread;
|
||||||
|
|
||||||
if (target.event_queue) |_| return error.ThreadQueueAlreadySet;
|
if (target.event_queue) |_| return error.ThreadQueueAlreadySet;
|
||||||
@ -54,3 +54,55 @@ pub fn setEventQueue(_: *platform.Registers, args: *sys.Arguments, _: *isize) an
|
|||||||
|
|
||||||
target.event_queue = RingBuffer.init(data, platform.PAGE_SIZE, true);
|
target.event_queue = RingBuffer.init(data, platform.PAGE_SIZE, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn createThread(_: *platform.Registers, _: *sys.Arguments, result: *isize) anyerror!void {
|
||||||
|
const core = cpu.thisCore();
|
||||||
|
if (!sys.checkToken(core, system.kernel.Token.CreateProcess)) return error.NotAuthorized;
|
||||||
|
|
||||||
|
const allocator = pmm.lockGlobalAllocator();
|
||||||
|
defer pmm.unlockGlobalAllocator();
|
||||||
|
|
||||||
|
const child = try thread.createThreadControlBlock(allocator);
|
||||||
|
thread.arch.initUserRegisters(&child.regs);
|
||||||
|
|
||||||
|
result.* = @bitCast(child.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setThreadEntry(_: *platform.Registers, args: *sys.Arguments, _: *isize) anyerror!void {
|
||||||
|
const core = cpu.thisCore();
|
||||||
|
if (!sys.checkToken(core, system.kernel.Token.CreateProcess)) return error.NotAuthorized;
|
||||||
|
const target = thread.lookupThreadById(args.arg0) orelse return error.NoSuchThread;
|
||||||
|
|
||||||
|
thread.arch.setAddress(&target.regs, args.arg1);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setThreadArguments(_: *platform.Registers, args: *sys.Arguments, _: *isize) anyerror!void {
|
||||||
|
const core = cpu.thisCore();
|
||||||
|
if (!sys.checkToken(core, system.kernel.Token.CreateProcess)) return error.NotAuthorized;
|
||||||
|
const target = thread.lookupThreadById(args.arg0) orelse return error.NoSuchThread;
|
||||||
|
|
||||||
|
thread.arch.setArguments(&target.regs, args.arg1, args.arg2);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setThreadStack(_: *platform.Registers, args: *sys.Arguments, _: *isize) anyerror!void {
|
||||||
|
const core = cpu.thisCore();
|
||||||
|
if (!sys.checkToken(core, system.kernel.Token.CreateProcess)) return error.NotAuthorized;
|
||||||
|
const target = thread.lookupThreadById(args.arg0) orelse return error.NoSuchThread;
|
||||||
|
|
||||||
|
thread.arch.setStack(&target.regs, args.arg1);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn startThread(_: *platform.Registers, args: *sys.Arguments, _: *isize) anyerror!void {
|
||||||
|
const core = cpu.thisCore();
|
||||||
|
if (!sys.checkToken(core, system.kernel.Token.CreateProcess)) return error.NotAuthorized;
|
||||||
|
const target = thread.lookupThreadById(args.arg0) orelse return error.NoSuchThread;
|
||||||
|
|
||||||
|
if (target.state != .Inactive) return;
|
||||||
|
|
||||||
|
thread.reviveThread(core, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getThreadId(_: *platform.Registers, _: *sys.Arguments, result: *isize) anyerror!void {
|
||||||
|
const core = cpu.thisCore();
|
||||||
|
result.* = @bitCast(core.current_thread.id);
|
||||||
|
}
|
||||||
|
@ -29,6 +29,13 @@ const syscalls = [_]SystemCall{
|
|||||||
sched.sleep,
|
sched.sleep,
|
||||||
sched.setEventQueue,
|
sched.setEventQueue,
|
||||||
tokens.setTokens,
|
tokens.setTokens,
|
||||||
|
mem.setAddressSpace,
|
||||||
|
sched.createThread,
|
||||||
|
sched.setThreadEntry,
|
||||||
|
sched.setThreadArguments,
|
||||||
|
sched.setThreadStack,
|
||||||
|
sched.startThread,
|
||||||
|
sched.getThreadId,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn invokeSyscall(number: usize, frame: *platform.Registers, args: *Arguments, retval: *isize) void {
|
pub fn invokeSyscall(number: usize, frame: *platform.Registers, args: *Arguments, retval: *isize) void {
|
||||||
|
@ -7,17 +7,22 @@ pub const SystemCall = enum(u64) {
|
|||||||
SetPriority, // requires Token.ThreadPriority
|
SetPriority, // requires Token.ThreadPriority
|
||||||
GetPriority,
|
GetPriority,
|
||||||
Sleep,
|
Sleep,
|
||||||
SetEventQueue, // requires Token.EventQueue
|
SetEventQueue, // requires Token.CreateProcess
|
||||||
SetTokens, // requires Token.Root
|
SetTokens, // requires Token.Root
|
||||||
SetAddressSpace, // requires Token.VirtualMemory
|
SetAddressSpace, // requires Token.CreateProcess
|
||||||
|
CreateThread, // requires Token.CreateProcess
|
||||||
|
SetThreadEntry, // requires Token.CreateProcess
|
||||||
|
SetThreadArguments, // requires Token.CreateProcess
|
||||||
|
SetThreadStack, // requires Token.CreateProcess
|
||||||
|
StartThread, // requires Token.CreateProcess
|
||||||
|
GetThreadId,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Token = enum(u64) {
|
pub const Token = enum(u64) {
|
||||||
Root = 1 << 0,
|
Root = 1 << 0,
|
||||||
PhysicalMemory = 1 << 1,
|
PhysicalMemory = 1 << 1,
|
||||||
ThreadPriority = 1 << 2,
|
ThreadPriority = 1 << 2,
|
||||||
EventQueue = 1 << 3,
|
CreateProcess = 1 << 3,
|
||||||
VirtualMemory = 1 << 4,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const SystemError = error{
|
pub const SystemError = error{
|
||||||
|
@ -1,58 +1,94 @@
|
|||||||
const kernel = @import("kernel.zig");
|
const kernel = @import("kernel.zig");
|
||||||
const target = @import("builtin").target;
|
const target = @import("builtin").target;
|
||||||
|
|
||||||
fn syscall(num: kernel.SystemCall, arg0: u64, arg1: u64) i64 {
|
fn syscall(num: kernel.SystemCall, arg0: u64, arg1: u64, arg2: u64) i64 {
|
||||||
return switch (target.cpu.arch) {
|
return switch (target.cpu.arch) {
|
||||||
.x86_64 => asm volatile ("int $66"
|
.x86_64 => asm volatile ("int $66"
|
||||||
: [result] "={rax}" (-> i64),
|
: [result] "={rax}" (-> i64),
|
||||||
: [num] "{rax}" (@intFromEnum(num)),
|
: [num] "{rax}" (@intFromEnum(num)),
|
||||||
[arg0] "{rdi}" (arg0),
|
[arg0] "{rdi}" (arg0),
|
||||||
[arg1] "{rsi}" (arg1),
|
[arg1] "{rsi}" (arg1),
|
||||||
|
[arg2] "{rdx}" (arg2),
|
||||||
),
|
),
|
||||||
else => @compileError("unsupported architecture"),
|
else => @compileError("unsupported architecture"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn print(arg: u64) void {
|
pub fn print(arg: u64) void {
|
||||||
_ = syscall(.Print, arg, 0);
|
_ = syscall(.Print, arg, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn allocFrame() !usize {
|
pub fn allocFrame() !usize {
|
||||||
const retval = syscall(.AllocFrame, 0, 0);
|
const retval = syscall(.AllocFrame, 0, 0, 0);
|
||||||
if (retval < 0) return error.OutOfMemory;
|
if (retval < 0) return error.OutOfMemory;
|
||||||
return @bitCast(retval);
|
return @bitCast(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lockFrame(address: u64) void {
|
pub fn lockFrame(address: u64) void {
|
||||||
_ = syscall(.LockFrame, address, 0);
|
_ = syscall(.LockFrame, address, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn freeFrame(address: u64) void {
|
pub fn freeFrame(address: u64) void {
|
||||||
_ = syscall(.FreeFrame, address, 0);
|
_ = syscall(.FreeFrame, address, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn yield() void {
|
pub fn yield() void {
|
||||||
_ = syscall(.Yield, 0, 0);
|
_ = syscall(.Yield, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setPriority(priority: u8) void {
|
pub fn setPriority(priority: u8) void {
|
||||||
_ = syscall(.SetPriority, priority, 0);
|
_ = syscall(.SetPriority, priority, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getPriority() u8 {
|
pub fn getPriority() u8 {
|
||||||
return @truncate(@as(u64, @bitCast(syscall(.GetPriority, 0, 0))));
|
return @truncate(@as(u64, @bitCast(syscall(.GetPriority, 0, 0, 0))));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sleep(ms: u64) void {
|
pub fn sleep(ms: u64) void {
|
||||||
_ = syscall(.Sleep, ms, 0);
|
_ = syscall(.Sleep, ms, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setEventQueue(pid: u64, address: u64) !void {
|
pub fn setEventQueue(pid: u64, address: u64) !void {
|
||||||
const retval = syscall(.SetEventQueue, pid, address);
|
const retval = syscall(.SetEventQueue, pid, address, 0);
|
||||||
if (retval < 0) return error.NoSuchThread;
|
if (retval < 0) return error.NoSuchThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setTokens(pid: u64, tokens: u64) !void {
|
pub fn setTokens(pid: u64, tokens: u64) !void {
|
||||||
const retval = syscall(.SetTokens, pid, tokens);
|
const retval = syscall(.SetTokens, pid, tokens, 0);
|
||||||
if (retval < 0) return error.NoSuchThread;
|
if (retval < 0) return error.NoSuchThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn setAddressSpace(pid: u64, address: u64) !void {
|
||||||
|
const retval = syscall(.SetAddressSpace, pid, address, 0);
|
||||||
|
if (retval < 0) return error.NoSuchThread;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn createThread() !u64 {
|
||||||
|
const retval = syscall(.CreateThread, 0, 0, 0);
|
||||||
|
if (retval < 0) return error.NoSuchThread;
|
||||||
|
return @bitCast(retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setThreadEntry(pid: u64, entry: u64) !void {
|
||||||
|
const retval = syscall(.SetThreadEntry, pid, entry, 0);
|
||||||
|
if (retval < 0) return error.NoSuchThread;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setThreadArguments(pid: u64, arg0: u64, arg1: u64) !void {
|
||||||
|
const retval = syscall(.SetThreadArguments, pid, arg0, arg1);
|
||||||
|
if (retval < 0) return error.NoSuchThread;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setThreadStack(pid: u64, stack: u64) !void {
|
||||||
|
const retval = syscall(.SetThreadStack, pid, stack, 0);
|
||||||
|
if (retval < 0) return error.NoSuchThread;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn startThread(pid: u64) !void {
|
||||||
|
const retval = syscall(.StartThread, pid, 0, 0);
|
||||||
|
if (retval < 0) return error.NoSuchThread;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getThreadId() u64 {
|
||||||
|
return @bitCast(syscall(.GetThreadId, 0, 0, 0));
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user