memory.heap¶
Bitmap-based kernel heap allocator providing kalloc, kfree, and large-allocation support.
Overview¶
memory.heap implements the Asuro logical memory manager (LMM). The heap is organized as a singly/doubly-linked list of 4 MiB virtual pages, each managed by a bitmap that tracks 8-byte allocation units.
Each heap page has the following layout:
| Region | Offset | Size |
|---|---|---|
THeapPageHeader |
0x000000 |
24 bytes |
| Bitmap | 0x000018 |
64,512 bytes (516,096 bits) |
| Padding | 0x00FC18 |
1,000 bytes |
| Data area | 0x010000 |
4,128,768 bytes (516,096 units × 8 bytes) |
Every allocation is preceded by a 16-byte prefix: 4 bytes for the unit count, 12 bytes of padding. This ensures the returned pointer is 16-byte aligned (required for SSE 128-bit operations) and allows kfree to recover the allocation size without a separate metadata structure.
Allocations larger than a single heap page's capacity are handled by klalloc, which maps contiguous virtual pages and stores a magic sentinel ($FFFFFFFE) in the header so kfree can identify them and call klfree instead of the normal bitmap path.
kalloc and kfree disable interrupts for the duration of their critical sections using a stack-balanced pushfd/cli/pop sequence and restore the interrupt flag via restore_if on all exit paths.
Dependencies¶
arch.x86.memory.physicalarch.x86.memory.virtualio.syslogdebug.tracercore.util,arch.x86.utilcore.panic
Constants¶
| Constant | Value | Description |
|---|---|---|
ALLOC_UNIT |
8 |
Bytes per allocation unit |
DATA_OFFSET |
$10000 (64 KiB) |
Offset from page base to data area |
PAGE_SIZE_LMM |
$400000 (4 MiB) |
Size of each heap virtual page |
TOTAL_UNITS |
516096 |
Allocation units per page ((PAGE_SIZE_LMM - DATA_OFFSET) / ALLOC_UNIT) |
BITMAP_DWORDS |
16128 |
32-bit words required to hold the bitmap |
SIZE_PREFIX |
16 |
Bytes prepended to every normal allocation |
LARGE_ALLOC_MAGIC |
$FFFFFFFE |
Sentinel written at offset +4 in klalloc headers |
GUARD_MAGIC |
$DEADBEEF |
Guard sentinel for overrun detection (debug builds only) |
Types¶
THeapPageHeader / PHeapPageHeader¶
THeapPageHeader = packed record
NextPage : PHeapPageHeader;
PrevPage : PHeapPageHeader;
FreeUnits : uint32;
NextFree : uint32;
TotalUnits : uint32;
Reserved : uint32;
end;
Located at the base address of each heap virtual page. NextFree is a roving hint that tracks the first bitmap index likely to contain free units, reducing average scan time for sequential allocations.
Functions and Procedures¶
init¶
Allocates the first heap page via new_heap_page, sets Root_Page and Search_Page to it. Panics if the root page cannot be allocated.
kalloc¶
Allocates size bytes from the heap. Returns a 16-byte-aligned pointer. Returns nil for zero-size requests. Delegates to klalloc for requests too large for a single page. Searches pages starting from Search_Page using the NextFree roving hint, allocating a new page if no existing page can satisfy the request. Calls core.panic.panic if the system is completely out of memory. The allocated region is zeroed before being returned.
kfree¶
Frees a previously allocated block. Detects large allocations by checking the magic sentinel at area - 12 and delegates to klfree if found. For normal allocations, reads the unit count prefix, validates the range and double-free guard, clears the bitmap range, updates FreeUnits and NextFree, and calls try_release_page to return completely-free pages to the VMM.
klalloc¶
Allocates size bytes by mapping contiguous virtual pages from the low virtual address range (page numbers 5 through KERNEL_PAGE_NUMBER - 1). Writes a header containing the page count and LARGE_ALLOC_MAGIC sentinel. Returns a pointer 16 bytes past the header. Returns nil if no contiguous range is available.
klfree¶
Frees a large allocation by reading the page count from the header at address and releasing each mapped virtual page back to the VMM. Validates the page count before proceeding.
kpalloc¶
Identity-maps a physical 4 MiB block at the specified address using force_alloc_block and map_page. Used for memory-mapped hardware regions that must appear at a fixed virtual address.
lmm_total_free¶
Returns the total free bytes across all heap pages by summing FreeUnits * ALLOC_UNIT for every page in the linked list.
lmm_page_count¶
Returns the number of heap pages currently in the linked list.
Notes¶
The restore_if helper checks bit 9 (IF) of the saved EFLAGS word and issues STI only if interrupts were enabled on entry. It uses STI rather than POPFD to avoid restoring potentially dangerous EFLAGS bits (IOPL, NT, VM, AC) that could trigger a General Protection Fault or Bad-TSS on the next IRET.
When DEBUG_LMM is defined, kalloc allocates one additional unit and writes GUARD_MAGIC at the end of the allocation. kfree verifies this sentinel before freeing; a mismatch triggers a GPF with a syslog error, catching buffer overruns at free time.
Double-free detection uses bitmap_all_set: if any bit in the allocation's range is already clear at free time, the allocator logs an error and GPFs rather than silently corrupting the bitmap.
Fully empty pages (other than the root page) are returned to the VMM by try_release_page, which unlinks the page from the doubly-linked list and calls arch.x86.memory.virtual.free_page_at_address.