diff --git a/src/kern/cpu.zig b/src/kern/cpu.zig index 1401ae9..ee672a5 100644 --- a/src/kern/cpu.zig +++ b/src/kern/cpu.zig @@ -1,6 +1,7 @@ const std = @import("std"); const rtl = @import("rtl"); const b = @import("base"); +const config = @import("config"); const ke = b.ke; const ki = b.ke.private; @@ -89,3 +90,44 @@ pub fn CpuLocal(comptime T: type, comptime init: T) type { } }; } + +/// Bitmask of CPUs. +pub const CpuMask = struct { + const bits_per_word = @sizeOf(usize) * 8; + const num_words = (config.CONFIG_NCPUS + bits_per_word - 1) / bits_per_word; + + bits: [num_words]usize, + + /// Return an empty `CpuMask`. + pub fn empty() CpuMask { + return CpuMask{ .bits = [_]usize{0} ** num_words }; + } + + /// Set the bit corresponding to `cpu_id`. + pub fn set(self: *CpuMask, cpu_id: usize) void { + const word_index = cpu_id / bits_per_word; + const bit_index = cpu_id % bits_per_word; + self.bits[word_index] |= (@as(usize, 1) << @intCast(bit_index)); + } + + /// Clear the bit corresponding to `cpu_id`. + pub fn clear(self: *CpuMask, cpu_id: usize) void { + const word_index = cpu_id / bits_per_word; + const bit_index = cpu_id % bits_per_word; + self.bits[word_index] &= ~(@as(usize, 1) << @intCast(bit_index)); + } + + /// Check whether the bit corresponding to `cpu_id` is set. + pub fn is_set(self: *const CpuMask, cpu_id: usize) bool { + const word_index = cpu_id / bits_per_word; + const bit_index = cpu_id % bits_per_word; + return (self.bits[word_index] & (@as(usize, 1) << @intCast(bit_index))) != 0; + } + + pub fn is_full(self: *const CpuMask) bool { + for (self.bits) |word| { + if (word != std.math.maxInt(usize)) return false; + } + return true; + } +}; diff --git a/src/kern/root.zig b/src/kern/root.zig index 3417576..fb710c3 100644 --- a/src/kern/root.zig +++ b/src/kern/root.zig @@ -54,6 +54,7 @@ pub const wait = struct { pub const Cpu = p.cpu.Cpu; pub const CpuLocal = p.cpu.CpuLocal; +pub const CpuMask = p.cpu.CpuMask; comptime { if (!@hasDecl(p.impl, "curcpu")) @compileError("impl must provide curcpu()");