Compare commits
No commits in common. "c80c7bbc6ed8f663ee4d8391c04d28074abdbba9" and "32ecd325e3d1ca1d134a1245e72a42692bd64cde" have entirely different histories.
c80c7bbc6e
...
32ecd325e3
@ -7,12 +7,8 @@ pub fn build(b: *std.Build) void {
|
||||
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const system_module = b.addModule("system", .{
|
||||
.root_source_file = b.path("system/lib/system.zig"),
|
||||
});
|
||||
|
||||
core.buildAsSubmodule(b, build_step, optimize, system_module);
|
||||
system.buildAsSubmodule(b, build_step, optimize, system_module);
|
||||
core.build(b, build_step, optimize);
|
||||
system.build(b, build_step, optimize);
|
||||
|
||||
b.default_step = build_step;
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ const std = @import("std");
|
||||
|
||||
const here = "core";
|
||||
|
||||
pub fn buildAsSubmodule(b: *std.Build, build_step: *std.Build.Step, optimize: std.builtin.OptimizeMode, system_module: *std.Build.Module) void {
|
||||
pub fn build(b: *std.Build, build_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
|
||||
var disabled_features = std.Target.Cpu.Feature.Set.empty;
|
||||
var enabled_features = std.Target.Cpu.Feature.Set.empty;
|
||||
|
||||
@ -38,8 +38,6 @@ pub fn buildAsSubmodule(b: *std.Build, build_step: *std.Build.Step, optimize: st
|
||||
},
|
||||
});
|
||||
|
||||
core.root_module.addImport("system", system_module);
|
||||
|
||||
var kernel_step = b.step("core", "Build the core microkernel");
|
||||
kernel_step.dependOn(&core.step);
|
||||
kernel_step.dependOn(&install.step);
|
||||
|
@ -2,8 +2,8 @@ const std = @import("std");
|
||||
const target = @import("builtin").target;
|
||||
const thread = @import("../thread.zig");
|
||||
const pmm = @import("../pmm.zig");
|
||||
const vmm = @import("vmm.zig");
|
||||
const platform = @import("platform.zig");
|
||||
const vmm = @import("vmm.zig").arch;
|
||||
const platform = @import("platform.zig").arch;
|
||||
|
||||
pub const arch = switch (target.cpu.arch) {
|
||||
.x86_64 => @import("x86_64/cpu.zig"),
|
||||
@ -30,7 +30,6 @@ pub fn setupCore(allocator: *pmm.FrameAllocator) !void {
|
||||
idle_thread.regs = std.mem.zeroes(@TypeOf(idle_thread.regs));
|
||||
idle_thread.state = .Running;
|
||||
idle_thread.user_priority = 0;
|
||||
idle_thread.event_queue = null;
|
||||
thread.arch.initKernelRegisters(&idle_thread.regs);
|
||||
thread.arch.setAddress(&idle_thread.regs, @intFromPtr(&thread.arch.idleLoop));
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
const std = @import("std");
|
||||
const target = @import("builtin").target;
|
||||
|
||||
pub usingnamespace switch (target.cpu.arch) {
|
||||
pub const arch = switch (target.cpu.arch) {
|
||||
.x86_64 => @import("x86_64/interrupts.zig"),
|
||||
else => {
|
||||
@compileError("unsupported architecture");
|
||||
|
@ -1,7 +1,7 @@
|
||||
const std = @import("std");
|
||||
const target = @import("builtin").target;
|
||||
|
||||
pub usingnamespace switch (target.cpu.arch) {
|
||||
pub const arch = switch (target.cpu.arch) {
|
||||
.x86_64 => @import("x86_64/platform.zig"),
|
||||
else => {
|
||||
@compileError("unsupported architecture");
|
||||
|
@ -1,7 +1,7 @@
|
||||
const std = @import("std");
|
||||
const target = @import("builtin").target;
|
||||
|
||||
pub usingnamespace switch (target.cpu.arch) {
|
||||
pub const arch = switch (target.cpu.arch) {
|
||||
.x86_64 => @import("x86_64/thread.zig"),
|
||||
else => {
|
||||
@compileError("unsupported architecture");
|
||||
|
@ -1,7 +1,7 @@
|
||||
const std = @import("std");
|
||||
const target = @import("builtin").target;
|
||||
|
||||
pub usingnamespace switch (target.cpu.arch) {
|
||||
pub const arch = switch (target.cpu.arch) {
|
||||
.x86_64 => @import("x86_64/vmm.zig"),
|
||||
else => {
|
||||
@compileError("unsupported architecture");
|
||||
|
@ -1,7 +1,7 @@
|
||||
const std = @import("std");
|
||||
const target = @import("builtin").target;
|
||||
const vmm = @import("arch/vmm.zig");
|
||||
const platform = @import("arch/platform.zig");
|
||||
const vmm = @import("arch/vmm.zig").arch;
|
||||
const platform = @import("arch/platform.zig").arch;
|
||||
const pmm = @import("pmm.zig");
|
||||
const debug = @import("arch/debug.zig");
|
||||
|
||||
|
@ -2,9 +2,9 @@ const std = @import("std");
|
||||
const easyboot = @cImport(@cInclude("easyboot.h"));
|
||||
const debug = @import("arch/debug.zig");
|
||||
const cpu = @import("arch/cpu.zig");
|
||||
const platform = @import("arch/platform.zig");
|
||||
const interrupts = @import("arch/interrupts.zig");
|
||||
const vmm = @import("arch/vmm.zig");
|
||||
const platform = @import("arch/platform.zig").arch;
|
||||
const interrupts = @import("arch/interrupts.zig").arch;
|
||||
const vmm = @import("arch/vmm.zig").arch;
|
||||
const multiboot = @import("multiboot.zig");
|
||||
const pmm = @import("pmm.zig");
|
||||
const thread = @import("thread.zig");
|
||||
|
@ -1,7 +1,7 @@
|
||||
const std = @import("std");
|
||||
const easyboot = @cImport(@cInclude("easyboot.h"));
|
||||
const platform = @import("arch/platform.zig");
|
||||
const vmm = @import("arch/vmm.zig");
|
||||
const platform = @import("arch/platform.zig").arch;
|
||||
const vmm = @import("arch/vmm.zig").arch;
|
||||
const mmap = @import("mmap.zig");
|
||||
const bmap = @import("lib/bitmap.zig");
|
||||
const locking = @import("lib/spinlock.zig");
|
||||
|
@ -1,4 +1,4 @@
|
||||
const platform = @import("../arch/platform.zig");
|
||||
const platform = @import("../arch/platform.zig").arch;
|
||||
const sys = @import("syscall.zig");
|
||||
const pmm = @import("../pmm.zig");
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
const platform = @import("../arch/platform.zig");
|
||||
const platform = @import("../arch/platform.zig").arch;
|
||||
const sys = @import("syscall.zig");
|
||||
const debug = @import("../arch/debug.zig");
|
||||
|
||||
|
@ -1,18 +1,7 @@
|
||||
const std = @import("std");
|
||||
const system = @import("system");
|
||||
const platform = @import("../arch/platform.zig");
|
||||
const platform = @import("../arch/platform.zig").arch;
|
||||
const sys = @import("syscall.zig");
|
||||
const thread = @import("../thread.zig");
|
||||
const cpu = @import("../arch/cpu.zig");
|
||||
const pmm = @import("../pmm.zig");
|
||||
const vmm = @import("../arch/vmm.zig");
|
||||
|
||||
const RingBuffer = system.ring_buffer.RingBuffer;
|
||||
|
||||
const SyscallError = error{
|
||||
NoSuchThread,
|
||||
ThreadQueueAlreadySet,
|
||||
};
|
||||
|
||||
pub fn yield(regs: *platform.Registers, _: *sys.Arguments, _: *isize) anyerror!void {
|
||||
const core = cpu.thisCore();
|
||||
@ -34,17 +23,3 @@ pub fn getPriority(_: *platform.Registers, _: *sys.Arguments, retval: *isize) an
|
||||
pub fn sleep(regs: *platform.Registers, args: *sys.Arguments, _: *isize) anyerror!void {
|
||||
_ = thread.startSleep(regs, args.arg0);
|
||||
}
|
||||
|
||||
pub fn setEventQueue(_: *platform.Registers, args: *sys.Arguments, _: *isize) anyerror!void {
|
||||
const target = thread.lookupThreadById(args.arg0) orelse return error.NoSuchThread;
|
||||
|
||||
if (target.event_queue) |_| return error.ThreadQueueAlreadySet;
|
||||
|
||||
const phys = pmm.PhysFrame{ .address = args.arg1 };
|
||||
|
||||
const virt = phys.virtualAddress(vmm.PHYSICAL_MAPPING_BASE);
|
||||
|
||||
const data: [*]u8 = @ptrFromInt(virt);
|
||||
|
||||
target.event_queue = RingBuffer.init(data, platform.PAGE_SIZE, true);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
const std = @import("std");
|
||||
const platform = @import("../arch/platform.zig");
|
||||
const print = @import("print.zig");
|
||||
const platform = @import("../arch/platform.zig").arch;
|
||||
const print = @import("print.zig").print;
|
||||
const mem = @import("mem.zig");
|
||||
const sched = @import("sched.zig");
|
||||
|
||||
@ -15,7 +15,7 @@ pub const Arguments = struct {
|
||||
|
||||
const SystemCall = *const fn (frame: *platform.Registers, args: *Arguments, retval: *isize) anyerror!void;
|
||||
|
||||
const syscalls = [_]SystemCall{ print.print, mem.allocFrame, mem.lockFrame, mem.freeFrame, sched.yield, sched.setPriority, sched.getPriority, sched.sleep, sched.setEventQueue };
|
||||
const syscalls = [_]SystemCall{ print, mem.allocFrame, mem.lockFrame, mem.freeFrame, sched.yield, sched.setPriority, sched.getPriority, sched.sleep };
|
||||
|
||||
pub fn invokeSyscall(number: usize, frame: *platform.Registers, args: *Arguments, retval: *isize) void {
|
||||
if (number >= syscalls.len) {
|
||||
|
@ -1,14 +1,11 @@
|
||||
const std = @import("std");
|
||||
const system = @import("system");
|
||||
const vmm = @import("arch/vmm.zig");
|
||||
const platform = @import("arch/platform.zig");
|
||||
const vmm = @import("arch/vmm.zig").arch;
|
||||
const platform = @import("arch/platform.zig").arch;
|
||||
const pmm = @import("pmm.zig");
|
||||
const cpu = @import("arch/cpu.zig");
|
||||
const locking = @import("lib/spinlock.zig");
|
||||
|
||||
const RingBuffer = system.ring_buffer.RingBuffer;
|
||||
|
||||
pub const arch = @import("arch/thread.zig");
|
||||
pub const arch = @import("arch/thread.zig").arch;
|
||||
|
||||
pub const ThreadState = enum {
|
||||
Inactive,
|
||||
@ -23,7 +20,6 @@ pub const ThreadControlBlock = struct {
|
||||
regs: platform.Registers,
|
||||
state: ThreadState,
|
||||
user_priority: u8,
|
||||
event_queue: ?RingBuffer,
|
||||
|
||||
// Managed by addThreadToGlobalList(), no need to set manually.
|
||||
tag: GlobalThreadList.Node,
|
||||
@ -150,7 +146,6 @@ pub fn createThreadControlBlock(allocator: *pmm.FrameAllocator) !*ThreadControlB
|
||||
thread.regs = std.mem.zeroes(@TypeOf(thread.regs));
|
||||
thread.state = .Inactive;
|
||||
thread.user_priority = 127;
|
||||
thread.event_queue = null;
|
||||
|
||||
addThreadToGlobalList(thread);
|
||||
|
||||
@ -319,7 +314,7 @@ pub fn lookupThreadById(id: u64) ?*ThreadControlBlock {
|
||||
|
||||
var it: ?*GlobalThreadList.Node = global_thread_list.first;
|
||||
while (it) |n| : (it = n.next) {
|
||||
const thread: *ThreadControlBlock = @alignCast(@fieldParentPtr("tag", n));
|
||||
const thread: *ThreadControlBlock = @fieldParentPtr("tag", n);
|
||||
if (thread.id == id) return thread;
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
const std = @import("std");
|
||||
const init = @import("init/build.zig");
|
||||
|
||||
pub fn buildAsSubmodule(b: *std.Build, build_step: *std.Build.Step, optimize: std.builtin.OptimizeMode, system_module: *std.Build.Module) void {
|
||||
pub fn build(b: *std.Build, build_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
|
||||
const system_step = b.step("system", "Build core system services");
|
||||
init.buildAsSubmodule(b, system_step, optimize, system_module);
|
||||
init.build(b, system_step, optimize);
|
||||
|
||||
build_step.dependOn(system_step);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
const std = @import("std");
|
||||
const target = @import("builtin").target;
|
||||
|
||||
pub usingnamespace switch (target.cpu.arch) {
|
||||
pub const arch = switch (target.cpu.arch) {
|
||||
.x86_64 => @import("x86_64/vm.zig"),
|
||||
else => {
|
||||
@compileError("unsupported architecture");
|
||||
|
@ -1,7 +1,5 @@
|
||||
const std = @import("std");
|
||||
const system = @import("system");
|
||||
|
||||
const syscalls = system.syscalls;
|
||||
const kernel = @import("../../kernel.zig");
|
||||
|
||||
const MapError = error{
|
||||
MemoryAlreadyInUse,
|
||||
@ -9,7 +7,7 @@ const MapError = error{
|
||||
OutOfMemory,
|
||||
};
|
||||
|
||||
pub const PhysFrame = struct {
|
||||
const PhysFrame = struct {
|
||||
address: u64,
|
||||
|
||||
pub fn virtualAddress(self: *const PhysFrame, base: usize) usize {
|
||||
@ -107,7 +105,7 @@ fn updatePageTableEntry(entry: *PageTableEntry, phys: PhysFrame, flags: u32) voi
|
||||
fn setUpParentPageTableEntry(mapper: *const MemoryMapper, pte: *PageTableEntry, flags: u32) !void {
|
||||
if (pte.present == 0) {
|
||||
pte.clear();
|
||||
const frame = PhysFrame{ .address = try syscalls.allocFrame() };
|
||||
const frame = PhysFrame{ .address = try kernel.allocFrame() };
|
||||
pte.present = 1;
|
||||
pte.setAddress(frame.address);
|
||||
getTable(mapper, pte).* = std.mem.zeroes(PageDirectory);
|
||||
|
@ -2,7 +2,7 @@ const std = @import("std");
|
||||
|
||||
const here = "system/init";
|
||||
|
||||
pub fn buildAsSubmodule(b: *std.Build, build_step: *std.Build.Step, optimize: std.builtin.OptimizeMode, system_module: *std.Build.Module) void {
|
||||
pub fn build(b: *std.Build, build_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
|
||||
var disabled_features = std.Target.Cpu.Feature.Set.empty;
|
||||
var enabled_features = std.Target.Cpu.Feature.Set.empty;
|
||||
|
||||
@ -29,8 +29,6 @@ pub fn buildAsSubmodule(b: *std.Build, build_step: *std.Build.Step, optimize: st
|
||||
.code_model = .default,
|
||||
});
|
||||
|
||||
init.root_module.addImport("system", system_module);
|
||||
|
||||
const install = b.addInstallArtifact(init, .{
|
||||
.dest_dir = .{
|
||||
.override = .{ .custom = "boot/" },
|
||||
|
56
system/init/kernel.zig
Normal file
56
system/init/kernel.zig
Normal file
@ -0,0 +1,56 @@
|
||||
const SystemCall = enum(u64) {
|
||||
Print,
|
||||
AllocFrame,
|
||||
LockFrame,
|
||||
FreeFrame,
|
||||
Yield,
|
||||
SetPriority,
|
||||
GetPriority,
|
||||
Sleep,
|
||||
};
|
||||
|
||||
const SystemError = error{
|
||||
OutOfMemory,
|
||||
};
|
||||
|
||||
fn syscall(num: SystemCall, arg: u64) i64 {
|
||||
return asm volatile ("int $66"
|
||||
: [result] "=r" (-> i64),
|
||||
: [num] "{rax}" (@intFromEnum(num)),
|
||||
[arg] "{rdi}" (arg),
|
||||
);
|
||||
}
|
||||
|
||||
pub fn print(arg: u64) void {
|
||||
_ = syscall(.Print, arg);
|
||||
}
|
||||
|
||||
pub fn allocFrame() !usize {
|
||||
const retval = syscall(.AllocFrame, 0);
|
||||
if (retval < 0) return error.OutOfMemory;
|
||||
return @bitCast(retval);
|
||||
}
|
||||
|
||||
pub fn lockFrame(address: u64) void {
|
||||
_ = syscall(.LockFrame, address);
|
||||
}
|
||||
|
||||
pub fn freeFrame(address: u64) void {
|
||||
_ = syscall(.FreeFrame, address);
|
||||
}
|
||||
|
||||
pub fn yield() void {
|
||||
_ = syscall(.Yield, 0);
|
||||
}
|
||||
|
||||
pub fn setPriority(priority: u8) void {
|
||||
_ = syscall(.SetPriority, priority);
|
||||
}
|
||||
|
||||
pub fn getPriority() u8 {
|
||||
return @truncate(@as(u64, @bitCast(syscall(.GetPriority, 0))));
|
||||
}
|
||||
|
||||
pub fn sleep(ms: u64) void {
|
||||
_ = syscall(.Sleep, ms);
|
||||
}
|
@ -1,30 +1,14 @@
|
||||
const system = @import("system");
|
||||
const vm = @import("arch/vm.zig");
|
||||
|
||||
const syscalls = system.syscalls;
|
||||
const buffer = system.ring_buffer;
|
||||
|
||||
// FIXME: Make arch-specific.
|
||||
const PAGE_SIZE = 4096;
|
||||
|
||||
fn setupKernelRingBuffer(base: u64) !buffer.RingBuffer {
|
||||
const phys = vm.PhysFrame{ .address = try syscalls.allocFrame() };
|
||||
|
||||
const data: [*]u8 = @ptrCast(phys.virtualPointer(u8, base));
|
||||
|
||||
try syscalls.setEventQueue(1, phys.address);
|
||||
|
||||
return buffer.RingBuffer.init(data, PAGE_SIZE, true);
|
||||
}
|
||||
const kernel = @import("kernel.zig");
|
||||
const vm = @import("arch/vm.zig").arch;
|
||||
|
||||
export fn _start(base: u64, address: u64) callconv(.C) noreturn {
|
||||
const mapper = vm.MemoryMapper.create(.{ .address = address }, base);
|
||||
|
||||
syscalls.print(base);
|
||||
syscalls.print(address);
|
||||
syscalls.print(@intFromPtr(mapper.directory));
|
||||
kernel.print(base);
|
||||
kernel.print(address);
|
||||
kernel.print(@intFromPtr(mapper.directory));
|
||||
|
||||
const phys = syscalls.allocFrame() catch {
|
||||
const phys = kernel.allocFrame() catch {
|
||||
while (true) {}
|
||||
};
|
||||
|
||||
@ -32,16 +16,10 @@ export fn _start(base: u64, address: u64) callconv(.C) noreturn {
|
||||
while (true) {}
|
||||
};
|
||||
|
||||
const event_queue = setupKernelRingBuffer(base) catch {
|
||||
while (true) {}
|
||||
};
|
||||
|
||||
_ = event_queue;
|
||||
|
||||
var counter: u64 = 0;
|
||||
|
||||
while (true) : (counter += 4) {
|
||||
syscalls.sleep(1000);
|
||||
syscalls.print(counter);
|
||||
kernel.sleep(1000);
|
||||
kernel.print(counter);
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +0,0 @@
|
||||
pub const SystemCall = enum(u64) {
|
||||
Print,
|
||||
AllocFrame,
|
||||
LockFrame,
|
||||
FreeFrame,
|
||||
Yield,
|
||||
SetPriority,
|
||||
GetPriority,
|
||||
Sleep,
|
||||
SetEventQueue,
|
||||
};
|
||||
|
||||
pub const SystemError = error{
|
||||
OutOfMemory,
|
||||
NoSuchThread,
|
||||
};
|
@ -1,130 +0,0 @@
|
||||
//! Single-producer single-consumer lockfree ring buffer, which supports reading and storing arbitrary amounts of bytes,
|
||||
//! and which supports being stored in shared memory, for usage in IPC.
|
||||
|
||||
const std = @import("std");
|
||||
|
||||
pub const RingBuffer = struct {
|
||||
const Data = packed struct {
|
||||
read_index: u16,
|
||||
write_index: u16,
|
||||
data_start: u8,
|
||||
};
|
||||
|
||||
capacity: u16,
|
||||
data: *Data,
|
||||
|
||||
pub fn init(buffer: [*]u8, length: u16, initialize: bool) RingBuffer {
|
||||
const data: *Data = @alignCast(@ptrCast(buffer));
|
||||
|
||||
if (initialize) {
|
||||
data.read_index = 0;
|
||||
data.write_index = 0;
|
||||
}
|
||||
|
||||
const capacity = length - (@sizeOf(@TypeOf(data.read_index)) + @sizeOf(@TypeOf(data.write_index)));
|
||||
|
||||
return .{ .capacity = capacity, .data = data };
|
||||
}
|
||||
|
||||
pub fn write(self: *RingBuffer, data: [*]const u8, length: usize) bool {
|
||||
const available = self.bytesAvailableToWrite();
|
||||
var tail = @atomicLoad(u16, &self.data.write_index, .monotonic);
|
||||
|
||||
const buffer = self.dataPointer();
|
||||
|
||||
const bytes_to_write = length;
|
||||
if (bytes_to_write == 0) return false;
|
||||
if (bytes_to_write > available) return false;
|
||||
if (self.capacity <= tail) return false;
|
||||
|
||||
var written: usize = 0;
|
||||
|
||||
// Write first segment: from tail up to the end of the buffer.
|
||||
const first_chunk = @min(bytes_to_write, self.capacity - tail);
|
||||
@memcpy(buffer[tail .. tail + first_chunk], data[0..first_chunk]);
|
||||
written += first_chunk;
|
||||
tail = (tail + first_chunk) % self.capacity;
|
||||
|
||||
// Write second segment if needed (wrap-around).
|
||||
if (written < bytes_to_write) {
|
||||
const second_chunk = bytes_to_write - written;
|
||||
@memcpy(buffer[0..second_chunk], data[first_chunk .. first_chunk + second_chunk]);
|
||||
tail = @intCast(second_chunk);
|
||||
written += second_chunk;
|
||||
}
|
||||
|
||||
@atomicStore(u16, &self.data.write_index, tail, .release);
|
||||
return true;
|
||||
}
|
||||
|
||||
fn read_impl(self: *RingBuffer, data: [*]u8, length: usize) ?u16 {
|
||||
const available = self.bytesAvailableToRead();
|
||||
var head = @atomicLoad(u16, &self.data.read_index, .monotonic);
|
||||
|
||||
const buffer = self.dataPointer();
|
||||
|
||||
const bytes_to_read = length;
|
||||
if (bytes_to_read == 0) return null;
|
||||
if (bytes_to_read > available) return null;
|
||||
if (self.capacity <= head) return null;
|
||||
|
||||
var bytes_read: usize = 0;
|
||||
|
||||
// Read first segment: from head up to the end of the buffer.
|
||||
const first_chunk = @min(bytes_to_read, self.capacity - head);
|
||||
@memcpy(data[0..first_chunk], buffer[head .. head + first_chunk]);
|
||||
bytes_read += first_chunk;
|
||||
head = (head + first_chunk) % self.capacity;
|
||||
|
||||
// Read second segment if needed (wrap-around).
|
||||
if (bytes_read < bytes_to_read) {
|
||||
const second_chunk = bytes_to_read - bytes_read;
|
||||
@memcpy(data[first_chunk .. first_chunk + second_chunk], buffer[0..second_chunk]);
|
||||
head = @intCast(second_chunk);
|
||||
bytes_read += second_chunk;
|
||||
}
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
pub fn peek(self: *RingBuffer, data: [*]u8, length: usize) bool {
|
||||
return switch (self.read_impl(data, length)) {
|
||||
null => false,
|
||||
else => true,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn read(self: *RingBuffer, data: [*]u8, length: usize) bool {
|
||||
const result = self.read_impl(data, length) orelse return false;
|
||||
|
||||
@atomicStore(u16, &self.data.read_index, result, .release);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
fn dataPointer(self: *RingBuffer) [*]u8 {
|
||||
return @ptrCast(&self.data.data_start);
|
||||
}
|
||||
|
||||
fn bytesAvailableToWrite(self: *RingBuffer) u16 {
|
||||
const head = @atomicLoad(u16, &self.data.read_index, .acquire);
|
||||
const tail = @atomicLoad(u16, &self.data.write_index, .monotonic);
|
||||
if (head >= self.capacity or tail >= self.capacity) return 0; // Who tampered with the indices??
|
||||
if (tail >= head) {
|
||||
return self.capacity - (tail - head) - 1;
|
||||
} else {
|
||||
return head - tail - 1;
|
||||
}
|
||||
}
|
||||
|
||||
fn bytesAvailableToRead(self: *RingBuffer) u16 {
|
||||
const head = @atomicLoad(u16, &self.data.read_index, .monotonic);
|
||||
const tail = @atomicLoad(u16, &self.data.write_index, .acquire);
|
||||
if (head >= self.capacity or tail >= self.capacity) return 0; // Who tampered with the indices??
|
||||
if (tail >= head) {
|
||||
return tail - head;
|
||||
} else {
|
||||
return self.capacity - (head - tail);
|
||||
}
|
||||
}
|
||||
};
|
@ -1,53 +0,0 @@
|
||||
const kernel = @import("kernel.zig");
|
||||
const target = @import("builtin").target;
|
||||
|
||||
fn syscall(num: kernel.SystemCall, arg0: u64, arg1: u64) i64 {
|
||||
return switch (target.cpu.arch) {
|
||||
.x86_64 => asm volatile ("int $66"
|
||||
: [result] "=r" (-> i64),
|
||||
: [num] "{rax}" (@intFromEnum(num)),
|
||||
[arg0] "{rdi}" (arg0),
|
||||
[arg1] "{rsi}" (arg1),
|
||||
),
|
||||
else => @compileError("unsupported architecture"),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn print(arg: u64) void {
|
||||
_ = syscall(.Print, arg, 0);
|
||||
}
|
||||
|
||||
pub fn allocFrame() !usize {
|
||||
const retval = syscall(.AllocFrame, 0, 0);
|
||||
if (retval < 0) return error.OutOfMemory;
|
||||
return @bitCast(retval);
|
||||
}
|
||||
|
||||
pub fn lockFrame(address: u64) void {
|
||||
_ = syscall(.LockFrame, address, 0);
|
||||
}
|
||||
|
||||
pub fn freeFrame(address: u64) void {
|
||||
_ = syscall(.FreeFrame, address, 0);
|
||||
}
|
||||
|
||||
pub fn yield() void {
|
||||
_ = syscall(.Yield, 0, 0);
|
||||
}
|
||||
|
||||
pub fn setPriority(priority: u8) void {
|
||||
_ = syscall(.SetPriority, priority, 0);
|
||||
}
|
||||
|
||||
pub fn getPriority() u8 {
|
||||
return @truncate(@as(u64, @bitCast(syscall(.GetPriority, 0, 0))));
|
||||
}
|
||||
|
||||
pub fn sleep(ms: u64) void {
|
||||
_ = syscall(.Sleep, ms, 0);
|
||||
}
|
||||
|
||||
pub fn setEventQueue(pid: u64, address: u64) !void {
|
||||
const retval = syscall(.SetEventQueue, pid, address);
|
||||
if (retval < 0) return error.NoSuchThread;
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
pub const kernel = @import("kernel.zig");
|
||||
pub const ring_buffer = @import("ring_buffer.zig");
|
||||
pub const syscalls = @import("syscalls.zig");
|
Loading…
x
Reference in New Issue
Block a user