]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
feat: pmm_alloc_blocks/pmm_free_blocks — contiguous physical page allocation for...
authorTulio A M Mendes <[email protected]>
Thu, 12 Feb 2026 03:34:23 +0000 (00:34 -0300)
committerTulio A M Mendes <[email protected]>
Fri, 13 Feb 2026 02:20:50 +0000 (23:20 -0300)
include/pmm.h
src/mm/pmm.c

index 404ddd9961020d3b96f84b31b2765ffad1e7bd41..76d58a15644588a7bb2aeb5ebbbb11db50212a59 100644 (file)
@@ -34,6 +34,12 @@ void pmm_arch_init(void* boot_info);
 // Allocate a single physical page
 void* pmm_alloc_page(void);
 
+// Allocate N contiguous physical pages (for DMA buffers etc.)
+void* pmm_alloc_blocks(uint32_t count);
+
+// Free N contiguous physical pages
+void pmm_free_blocks(void* ptr, uint32_t count);
+
 // Free a physical page (decrements refcount, frees at 0)
 void pmm_free_page(void* ptr);
 
index 16046c8d8ca5ed00a95d058248f5525e4e4f15f9..351bc3ba7f2e73109135cdeed74698a6085617aa 100644 (file)
@@ -166,6 +166,43 @@ void* pmm_alloc_page(void) {
     return NULL; // OOM
 }
 
+void* pmm_alloc_blocks(uint32_t count) {
+    if (count == 0) return NULL;
+    if (count == 1) return pmm_alloc_page();
+
+    uintptr_t flags = spin_lock_irqsave(&pmm_lock);
+
+    for (uint64_t start = 1; start + count <= max_frames; start++) {
+        int found = 1;
+        for (uint32_t j = 0; j < count; j++) {
+            if (bitmap_test(start + j)) {
+                start += j; /* skip ahead past the used frame */
+                found = 0;
+                break;
+            }
+        }
+        if (found) {
+            for (uint32_t j = 0; j < count; j++) {
+                bitmap_set(start + j);
+                frame_refcount[start + j] = 1;
+                used_memory += PAGE_SIZE;
+            }
+            spin_unlock_irqrestore(&pmm_lock, flags);
+            return (void*)(uintptr_t)(start * PAGE_SIZE);
+        }
+    }
+
+    spin_unlock_irqrestore(&pmm_lock, flags);
+    return NULL;
+}
+
+void pmm_free_blocks(void* ptr, uint32_t count) {
+    uintptr_t addr = (uintptr_t)ptr;
+    for (uint32_t i = 0; i < count; i++) {
+        pmm_free_page((void*)(addr + i * PAGE_SIZE));
+    }
+}
+
 void pmm_free_page(void* ptr) {
     uintptr_t addr = (uintptr_t)ptr;
     uint64_t frame = addr / PAGE_SIZE;