]> 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 855e83359e4af46165bd26fb64dbcec35454cfc5..352dafa0105cb62d57ee06b361339730026f9aeb 100644 (file)
@@ -25,6 +25,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 9150354f6b4dc7b22d32b69a8036b3ff94241a7e..71456bd2d3d8aa13e2bb5c15d3c6a2132fb89bc1 100644 (file)
@@ -157,6 +157,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;