summaryrefslogtreecommitdiff
path: root/src/memory.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/memory.zig')
-rw-r--r--src/memory.zig50
1 files changed, 45 insertions, 5 deletions
diff --git a/src/memory.zig b/src/memory.zig
index f30e4392..e5394b4f 100644
--- a/src/memory.zig
+++ b/src/memory.zig
@@ -44,7 +44,48 @@ pub const Allocators = struct {
pdf: Allocator,
};
-var pardes_fallback: std.heap.StackFallbackAllocator(limits.arena.pardes) = undefined;
+/// `std.heap.StackFallbackAllocator` with the buffer taken through its
+/// lock-free interface. The core's allocator is used from two threads: a 9P
+/// connection task answers a request while the editor's own thread is out
+/// in a syscall that allocates (`readFileLimit`, `grep`; see `pardes.turn`).
+fn SharedStackFallback(comptime size: usize) type {
+ return struct {
+ buffer: [size]u8 = undefined,
+ fallback_allocator: Allocator = undefined,
+ fixed: std.heap.FixedBufferAllocator = undefined,
+
+ fn get(self: *@This()) Allocator {
+ self.fixed = .init(self.buffer[0..]);
+ return .{ .ptr = self, .vtable = &.{ .alloc = alloc, .resize = resize, .remap = remap, .free = free } };
+ }
+
+ fn alloc(ctx: *anyopaque, len: usize, alignment: std.mem.Alignment, ra: usize) ?[*]u8 {
+ const self: *@This() = @ptrCast(@alignCast(ctx));
+ return self.fixed.threadSafeAllocator().rawAlloc(len, alignment, ra) orelse
+ self.fallback_allocator.rawAlloc(len, alignment, ra);
+ }
+
+ fn resize(ctx: *anyopaque, buf: []u8, alignment: std.mem.Alignment, new_len: usize, ra: usize) bool {
+ const self: *@This() = @ptrCast(@alignCast(ctx));
+ if (self.fixed.ownsPtr(buf.ptr)) return self.fixed.threadSafeAllocator().rawResize(buf, alignment, new_len, ra);
+ return self.fallback_allocator.rawResize(buf, alignment, new_len, ra);
+ }
+
+ fn remap(ctx: *anyopaque, buf: []u8, alignment: std.mem.Alignment, new_len: usize, ra: usize) ?[*]u8 {
+ const self: *@This() = @ptrCast(@alignCast(ctx));
+ if (self.fixed.ownsPtr(buf.ptr)) return self.fixed.threadSafeAllocator().rawRemap(buf, alignment, new_len, ra);
+ return self.fallback_allocator.rawRemap(buf, alignment, new_len, ra);
+ }
+
+ fn free(ctx: *anyopaque, buf: []u8, alignment: std.mem.Alignment, ra: usize) void {
+ const self: *@This() = @ptrCast(@alignCast(ctx));
+ if (self.fixed.ownsPtr(buf.ptr)) return self.fixed.threadSafeAllocator().rawFree(buf, alignment, ra);
+ return self.fallback_allocator.rawFree(buf, alignment, ra);
+ }
+ };
+}
+
+var pardes_fallback: SharedStackFallback(limits.arena.pardes) = .{};
var frame_fallback: std.heap.StackFallbackAllocator(limits.arena.frame) = undefined;
var tree_sitter_fallback: std.heap.StackFallbackAllocator(limits.arena.tree_sitter) = undefined;
var image_fallback: std.heap.StackFallbackAllocator(limits.arena.image) = undefined;
@@ -61,7 +102,6 @@ var pdf_debug: Debug = .init;
// One session at a time; free its allocations before deinit. Concurrent LSP workers use the caller's allocator.
pub fn init(fallback: Allocator) Allocators {
pardes_fallback.fallback_allocator = fallback;
- pardes_fallback.get_called = if (std.debug.runtime_safety) false else {};
frame_fallback.fallback_allocator = fallback;
frame_fallback.get_called = if (std.debug.runtime_safety) false else {};
tree_sitter_fallback.fallback_allocator = fallback;
@@ -112,12 +152,12 @@ test "fixed allocators are separate, spill, and restart" {
var allocs = init(std.testing.allocator);
const core = try allocs.pardes.alloc(u8, 32);
const frame = try allocs.frame.alloc(u8, 32);
- try std.testing.expect(pardes_fallback.fixed_buffer_allocator.ownsPtr(core.ptr));
+ try std.testing.expect(pardes_fallback.fixed.ownsPtr(core.ptr));
try std.testing.expect(frame_fallback.fixed_buffer_allocator.ownsPtr(frame.ptr));
try std.testing.expect(core.ptr != frame.ptr);
const spill = try allocs.pardes.alloc(u8, limits.arena.pardes + 1);
- try std.testing.expect(!pardes_fallback.fixed_buffer_allocator.ownsPtr(spill.ptr));
+ try std.testing.expect(!pardes_fallback.fixed.ownsPtr(spill.ptr));
allocs.pardes.free(spill);
allocs.frame.free(frame);
allocs.pardes.free(core);
@@ -127,7 +167,7 @@ test "fixed allocators are separate, spill, and restart" {
defer deinit();
const restarted = try allocs.pardes.alloc(u8, 32);
defer allocs.pardes.free(restarted);
- try std.testing.expect(pardes_fallback.fixed_buffer_allocator.ownsPtr(restarted.ptr));
+ try std.testing.expect(pardes_fallback.fixed.ownsPtr(restarted.ptr));
}
test "memory limits preserve desktop capacities" {