summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTaylan Kammer <taylan.kammer@gmail.com>2026-08-23 22:10:35 +0200
committerTaylan Kammer <taylan.kammer@gmail.com>2026-08-23 22:10:35 +0200
commitc3f4ec8d940bee1dae5ff17e07a270eabce9d732 (patch)
tree4e546ca17508f5d75b93dd0bf7390217563e94ff /src
parentda11070351141256bbe99cbda18fea6929388daf (diff)
Meta Alloc can now reserve-only, later commit.
Diffstat (limited to 'src')
-rw-r--r--src/zisp/gc/meta_alloc.zig60
1 files changed, 51 insertions, 9 deletions
diff --git a/src/zisp/gc/meta_alloc.zig b/src/zisp/gc/meta_alloc.zig
index aa21967..c8d46e1 100644
--- a/src/zisp/gc/meta_alloc.zig
+++ b/src/zisp/gc/meta_alloc.zig
@@ -99,7 +99,7 @@ const SLAB_LEN: UnitIdx = 1 << 31;
/// A slab of memory.
const Slab = [SLAB_LEN]Unit;
-/// A pointer to a slot of allocated memory; N units depenging on size class.
+/// A pointer to a slot of allocated memory; N units depending on size class.
const SlotPtr = [*]Unit;
/// Size classes.
@@ -200,21 +200,59 @@ const TlSlabInfo = struct {
/// Thread-local metadata per slab / size class.
threadlocal var tl_slab_infos: [SIZES.len]TlSlabInfo = @splat(.{});
-/// Wrapper around std.posix.mmap().
-fn mmap(size: usize) []align(4096) u8 {
- return std.posix.mmap(
+/// Wrapper around the platform's mmap() or equivalent. The 'commit' argument
+/// indicates whether read/write access should already be enabled. If false,
+/// one must later use mcommit() to enable part or all of it.
+fn mmap(size: usize, commit: bool) [*]align(4096) u8 {
+ // TODO: MS Windows
+ const ret = std.c.mmap(
null,
size,
- .{ .READ = true, .WRITE = true },
+ .{ .READ = commit, .WRITE = commit },
.{ .TYPE = .PRIVATE, .ANONYMOUS = true },
-1,
0,
- ) catch @panic("Syscall mmap() failed.");
+ );
+ if (ret == std.c.MAP_FAILED) {
+ // TODO: Report reason.
+ @panic("Failed to map memory.");
+ }
+ return @ptrCast(@alignCast(ret));
+}
+
+/// Signal to the platform that we now require slab[0..idx] to be accessible.
+fn mcommit(slab: *Slab, idx: UnitIdx) void {
+ // TODO: MS Windows
+ const ptr: *align(4096) anyopaque = @ptrCast(@alignCast(slab));
+ const len: usize = idx * @sizeOf(Unit);
+ const ret = std.c.mprotect(
+ ptr,
+ len,
+ .{ .READ = true, .WRITE = true },
+ );
+ if (ret == -1) {
+ // TODO: Report reason.
+ @panic("Failed to commit memory.");
+ }
+}
+
+/// Signal to the platform that slab[idx..len] can be discarded, so it doesn't
+/// need physical backing memory until we write to it again. This does *not*
+/// undo mcommit(), so there is no need to call it again.
+fn mdiscard(ptr: [*]const u8, len: usize) void {
+ // TODO: MS Windows
+ const ret = std.c.madvise(
+ ptr,
+ len,
+ std.c.MADV.DONTNEED,
+ );
+ // Practically can't happen.
+ std.debug.assert(ret != -1);
}
/// Must call this once to initialize the slabs.
export fn init() void {
- slabs = @ptrCast(mmap(SIZES.len * SLAB_LEN * @sizeOf(Unit)));
+ slabs = @ptrCast(mmap(SIZES.len * SLAB_LEN * @sizeOf(Unit), false));
}
/// Allocate a slot of the given size, which must be a power of two and greater
@@ -226,7 +264,7 @@ export fn alloc(size: usize) [*]u8 {
@branchHint(.likely);
return @ptrCast(alloc_size_class(sci, size));
} else {
- return mmap(size).ptr;
+ return mmap(size, true);
}
}
@@ -237,7 +275,9 @@ export fn free(size: usize, ptr: [*]u8) void {
@branchHint(.likely);
free_size_class(sci, @ptrCast(@alignCast(ptr)));
} else {
- std.posix.munmap(@alignCast(ptr[0..size]));
+ const ret = std.c.munmap(@ptrCast(@alignCast(ptr)), size);
+ // Practically can't happen.
+ std.debug.assert(ret != -1);
}
}
@@ -396,6 +436,8 @@ fn alloc_fresh(
std.debug.panic("Exhausted slab for size class: {}", .{size});
}
+ mcommit(slab, new_wm);
+
tl.wm_hi = new_wm;
tl.wm_lo = old_wm + slot_len;
return slab[old_wm..].ptr;