diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-06 18:11:36 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-09-07 13:59:12 -0300 |
| commit | 60367d8fe23f6af98ec28e3cf6c2094dfe332df0 (patch) | |
| tree | 310fc734173cf771881f4691c71909135fadde97 /src/memory.zig | |
| parent | fa82cac885cb4738fe36d1e49b4749b5a3e31a4a (diff) | |
| download | pardes-60367d8fe23f6af98ec28e3cf6c2094dfe332df0.tar.gz pardes-60367d8fe23f6af98ec28e3cf6c2094dfe332df0.zip | |
Refactor panes and filesystem; replace FUSE with 9P
Consolidate pane, layout, memory and host code. Serve 9P by default over Unix sockets, with runtime mounts and optional TCP/QUIC transports. Remove FUSE and obsolete proof-of-concept examples.
Fix highlighting and terminal-history performance, expand differential and stress-test infrastructure, sort navigation results while preserving the next occurrence, add syntax-colored Braille minimaps, remove SPC-k, and document 9P interaction as a repository skill.
Diffstat (limited to 'src/memory.zig')
| -rw-r--r-- | src/memory.zig | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/src/memory.zig b/src/memory.zig new file mode 100644 index 00000000..60ec1bb6 --- /dev/null +++ b/src/memory.zig @@ -0,0 +1,148 @@ +const std = @import("std"); +const builtin = @import("builtin"); +const config = @import("pardes_config"); + +const board = config.platform == .esp32p4; +const reduced_target = builtin.os.tag == .freestanding; +const KiB = 1024; +const MiB = 1024 * KiB; + +pub const limits = struct { + pub const max_file_bytes = 256 * MiB; + pub const max_stream_bytes = 4 * MiB; + // P4: 384 KiB heap; static buffers and stack share a separate 240 KiB region. + pub const board_heap_bytes = 384 * KiB; + pub const effect_cap = if (board) 128 else 4096; + pub const pending_write_cap: usize = if (board) 0 else 4 * MiB; + pub const wrap_rows = if (board) 128 else 256; + pub const undo_max = if (board) 16 else 256; + pub const message_log = if (board) 16 else 128; + pub const max_tag_tail: usize = if (board) 512 else 4096; + pub const host_path_cap: usize = if (board) 0 else 4095; + pub const embedded_sources = !board; + pub const hexdump_row_bytes: u32 = if (board) 8 else 16; + + pub const arena = struct { + pub const pardes = if (board) 4 * KiB else if (reduced_target) 8 * MiB else 32 * MiB; + pub const frame = if (board) 4 * KiB else if (reduced_target) 4 * MiB else 16 * MiB; + pub const tree_sitter = if (board) 0 else if (reduced_target) 4 * MiB else 16 * MiB; + pub const image = if (board) 0 else if (reduced_target) 64 * KiB else 32 * MiB; + pub const pdf = if (board) 0 else if (reduced_target or !config.mupdf) 64 * KiB else 64 * MiB; + }; +}; + +const Allocator = std.mem.Allocator; +const debug_enabled = builtin.mode == .Debug; + +pub const Allocators = struct { + pardes: Allocator, + frame: Allocator, + lsp: Allocator, + tree_sitter: Allocator, + image: Allocator, + pdf: Allocator, +}; + +var pardes_fallback: std.heap.StackFallbackAllocator(limits.arena.pardes) = undefined; +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; +var pdf_fallback: std.heap.StackFallbackAllocator(limits.arena.pdf) = undefined; + +const Debug = std.heap.DebugAllocator(.{}); +var pardes_debug: Debug = .init; +var frame_debug: Debug = .init; +var lsp_debug: Debug = .init; +var tree_sitter_debug: Debug = .init; +var image_debug: Debug = .init; +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; + tree_sitter_fallback.get_called = if (std.debug.runtime_safety) false else {}; + image_fallback.fallback_allocator = fallback; + image_fallback.get_called = if (std.debug.runtime_safety) false else {}; + pdf_fallback.fallback_allocator = fallback; + pdf_fallback.get_called = if (std.debug.runtime_safety) false else {}; + + const raw: Allocators = .{ + .pardes = pardes_fallback.get(), + .frame = frame_fallback.get(), + .lsp = fallback, + .tree_sitter = tree_sitter_fallback.get(), + .image = image_fallback.get(), + .pdf = pdf_fallback.get(), + }; + if (!debug_enabled) return raw; + + pardes_debug = .{ .backing_allocator = raw.pardes }; + frame_debug = .{ .backing_allocator = raw.frame }; + lsp_debug = .{ .backing_allocator = raw.lsp }; + tree_sitter_debug = .{ .backing_allocator = raw.tree_sitter }; + image_debug = .{ .backing_allocator = raw.image }; + pdf_debug = .{ .backing_allocator = raw.pdf }; + return .{ + .pardes = pardes_debug.allocator(), + .frame = frame_debug.allocator(), + .lsp = lsp_debug.allocator(), + .tree_sitter = tree_sitter_debug.allocator(), + .image = image_debug.allocator(), + .pdf = pdf_debug.allocator(), + }; +} + +pub fn deinit() void { + if (!debug_enabled) return; + var leaked = pardes_debug.deinit() == .leak; + leaked = (frame_debug.deinit() == .leak) or leaked; + leaked = (lsp_debug.deinit() == .leak) or leaked; + leaked = (tree_sitter_debug.deinit() == .leak) or leaked; + leaked = (image_debug.deinit() == .leak) or leaked; + leaked = (pdf_debug.deinit() == .leak) or leaked; + if (leaked) @panic("allocator leaks detected"); +} + +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(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)); + allocs.pardes.free(spill); + allocs.frame.free(frame); + allocs.pardes.free(core); + deinit(); + + allocs = init(std.testing.allocator); + 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)); +} + +test "memory limits preserve desktop capacities" { + if (board or reduced_target) return error.SkipZigTest; + try std.testing.expectEqual(4096, limits.effect_cap); + try std.testing.expectEqual(@as(usize, 4 * MiB), limits.pending_write_cap); + try std.testing.expectEqual(256, limits.wrap_rows); + try std.testing.expectEqual(256, limits.undo_max); + try std.testing.expectEqual(128, limits.message_log); + try std.testing.expectEqual(@as(usize, 4096), limits.max_tag_tail); + try std.testing.expectEqual(@as(usize, 4095), limits.host_path_cap); + try std.testing.expect(limits.embedded_sources); + try std.testing.expectEqual(@as(u32, 16), limits.hexdump_row_bytes); + try std.testing.expectEqual(32 * MiB, limits.arena.pardes); + try std.testing.expectEqual(16 * MiB, limits.arena.frame); + try std.testing.expectEqual(16 * MiB, limits.arena.tree_sitter); + try std.testing.expectEqual(32 * MiB, limits.arena.image); + try std.testing.expectEqual(if (config.mupdf) 64 * MiB else 64 * KiB, limits.arena.pdf); +} |
