const std = @import("std"); const Page = extern struct { next: *Page, }; var head = @extern(*align(4096) Page, .{ .name = "_heap_start" }); pub fn init() void { // how many pages do we have? const page_count = @intFromPtr(@extern( *const anyopaque, .{ .name = "_heap_size" }, )) / 4096; // go through every page and make it point it to the next one const pages: []Page = @as([*]Page, @ptrCast(head))[0..page_count]; for (0..page_count - 1) |i| { pages[i].next = &pages[i + 1]; } std.log.scoped(.mem).info( "{} physical pages of 4096 B = {} B free", .{ page_count, page_count * 4096 }, ); } // allocates 1 page by taking it off the front of the linked list pub fn alloc() []align(4096) u8 { const page = @as([*]align(4096) u8, @ptrCast(head))[0..4096]; head = head.next; return page; } // free the page by putting it back on the front of the linked list pub fn free(mem: []align(4096) u8) void { std.debug.assert(mem.len == 4096); const page: *Page = @ptrCast(mem.ptr); page.next = head; head = page; }