aboutsummaryrefslogtreecommitdiff
path: root/mirai/memory/zone/alloc/alloc.zig
diff options
context:
space:
mode:
authorBobby <[email protected]>2026-03-30 15:02:42 +0530
committerBobby <[email protected]>2026-03-30 15:02:42 +0530
commit2324951126b542aeecfd8dd12b381265cce1566c (patch)
treea580fe97a13788fbe3b104e3a9553f551c2bff11 /mirai/memory/zone/alloc/alloc.zig
parent3c2c5c419cae1b7f2d60e8a3dc6e2e8c157b5a2f (diff)
downloadakiba-main.tar.xz
akiba-main.zip
refactor: reorganize kernel structure and implement memory management zonesHEADmain
Diffstat (limited to 'mirai/memory/zone/alloc/alloc.zig')
-rw-r--r--mirai/memory/zone/alloc/alloc.zig119
1 files changed, 119 insertions, 0 deletions
diff --git a/mirai/memory/zone/alloc/alloc.zig b/mirai/memory/zone/alloc/alloc.zig
new file mode 100644
index 0000000..00f9cef
--- /dev/null
+++ b/mirai/memory/zone/alloc/alloc.zig
@@ -0,0 +1,119 @@
+//! Zone Allocation
+
+const types = @import("../types/types.zig");
+const Zone = types.Zone;
+const ZonePageMeta = types.ZonePageMeta;
+const FreeElement = types.FreeElement;
+const page_size = types.page_size;
+
+const bootstrap = @import("../bootstrap/bootstrap.zig");
+const convert = @import("../../convert/convert.zig");
+const pmm = @import("../../../pmm/pmm.zig");
+
+pub const AllocError = error{
+ OutOfMemory,
+};
+
+pub fn zalloc(zone: *Zone) AllocError!*anyopaque {
+ if (zone.partial_pages == null) {
+ try expand(zone);
+ }
+
+ const page = zone.partial_pages orelse return AllocError.OutOfMemory;
+ const elem = page.free_list orelse return AllocError.OutOfMemory;
+
+ page.free_list = elem.next;
+ page.in_use += 1;
+ zone.alloc_count += 1;
+
+ if (page.free_list == null) {
+ zone.partial_pages = page.next;
+ page.next = zone.full_pages;
+ zone.full_pages = page;
+ }
+
+ return @ptrCast(elem);
+}
+
+pub fn zalloc_zeroed(zone: *Zone) AllocError!*anyopaque {
+ const ptr = try zalloc(zone);
+ const bytes: [*]u8 = @ptrCast(ptr);
+ @memset(bytes[0..zone.elem_size], 0);
+ return ptr;
+}
+
+pub fn zfree(zone: *Zone, ptr: *anyopaque) void {
+ const page_virt = @intFromPtr(ptr) & ~@as(usize, page_size - 1);
+ const page = find_page(zone, page_virt) orelse return;
+ const was_full = (page.free_list == null);
+
+ const elem: *FreeElement = @ptrCast(@alignCast(ptr));
+ elem.next = page.free_list;
+ page.free_list = elem;
+ page.in_use -|= 1;
+ zone.free_count += 1;
+
+ if (was_full) {
+ remove_from_full(zone, page);
+ page.next = zone.partial_pages;
+ zone.partial_pages = page;
+ }
+}
+
+fn expand(zone: *Zone) AllocError!void {
+ const phys = pmm.allocate_page() catch return AllocError.OutOfMemory;
+ const virt = convert.phys_to_virt(phys);
+
+ const page_meta_zone = bootstrap.get_page_meta_zone();
+ const meta_ptr = zalloc(page_meta_zone) catch {
+ pmm.free_page(phys);
+ return AllocError.OutOfMemory;
+ };
+ const meta: *ZonePageMeta = @ptrCast(@alignCast(meta_ptr));
+
+ meta.zone = zone;
+ meta.page_phys = phys;
+ meta.page_virt = virt;
+ meta.free_list = null;
+ meta.in_use = 0;
+ meta.next = zone.partial_pages;
+ zone.partial_pages = meta;
+ zone.page_count += 1;
+
+ const base: [*]u8 = @ptrFromInt(virt);
+ var offset: usize = 0;
+ while (offset + zone.elem_size <= page_size) : (offset += zone.elem_size) {
+ const elem: *FreeElement = @ptrCast(@alignCast(base + offset));
+ elem.next = meta.free_list;
+ meta.free_list = elem;
+ }
+}
+
+fn find_page(zone: *Zone, page_virt: usize) ?*ZonePageMeta {
+ var current = zone.partial_pages;
+ while (current) |page_meta| {
+ if (page_meta.page_virt == page_virt) return page_meta;
+ current = page_meta.next;
+ }
+ current = zone.full_pages;
+ while (current) |page_meta| {
+ if (page_meta.page_virt == page_virt) return page_meta;
+ current = page_meta.next;
+ }
+ return null;
+}
+
+fn remove_from_full(zone: *Zone, target: *ZonePageMeta) void {
+ if (zone.full_pages == target) {
+ zone.full_pages = target.next;
+ return;
+ }
+ var current = zone.full_pages;
+ while (current) |page_meta| {
+ if (page_meta.next == target) {
+ page_meta.next = target.next;
+ return;
+ }
+ current = page_meta.next;
+ }
+}