Skip to content

PageEntry

Description

Per-live-allocation descriptor. The byte count is the rounded mmap length (a multiple of the OS page size), which is what munmap / VirtualFree need. The user pointer is the mmap’d base address.

Usage example (Cross-references)

Usage examples (Cross-references)
            void *ptr;
            size  bytes;
        } PageEntry;
    
        ///
            Allocator  base;
            size       cached_page_size;
            PageEntry *entries;
            u32        len;
            u32        cap;
            u32        cap;
            size       entries_bytes;
            PageEntry *free_entries;
            u32        free_len;
            u32        free_cap;
            LOG_FATAL("PageAllocator: entries / entries_bytes mismatch");
        }
        if (pg->entries && pg->entries_bytes < (size)pg->cap * sizeof(PageEntry)) {
            LOG_FATAL(
                "PageAllocator: entries_bytes {} too small for cap {} (need {})",
                (u64)pg->entries_bytes,
                (u64)pg->cap,
                (u64)((size)pg->cap * sizeof(PageEntry))
            );
        }
    // detection on the live-region path; the retained-region table is
    // sorted by `bytes` and uses `page_free_find_size_match` instead.
    static u32 page_find_idx_sorted(const PageEntry *arr, u32 len, const void *ptr) {
        u32 lo = 0, hi = len;
        while (lo < hi) {
    // field pointers so the same helper grows either `entries` or
    // `free_entries`. Returns false on OS-allocation failure or overflow.
    static bool page_table_grow_into(PageAllocator *page, PageEntry **arr_p, u32 *len_p, u32 *cap_p, size *bytes_p) {
        size page_size = PageAllocatorPageSize(page);
        size want_bytes;
            return false;
        }
        PageEntry *new_table = (PageEntry *)os_page_map(&page->base, new_rounded);
        if (!new_table) {
            return false;
        }
        if (*arr_p) {
            MemCopy(new_table, *arr_p, (size)*len_p * sizeof(PageEntry));
            os_page_unmap(&page->base, *arr_p, *bytes_p);
        }
        *arr_p   = new_table;
        *bytes_p = new_rounded;
        *cap_p   = (u32)(new_rounded / sizeof(PageEntry));
        PAGE_MARK_DIRTY(page);
        return true;
    static bool page_table_insert_sorted(
        PageAllocator *page,
        PageEntry    **arr_p,
        u32           *len_p,
        u32           *cap_p,
            return false;
        }
        PageEntry *arr = *arr_p;
        u32        lo  = 0;
        u32        hi  = *len_p;
        u32 to_move = *len_p - ins;
        if (to_move > 0u) {
            MemMove(&arr[ins + 1u], &arr[ins], (size)to_move * sizeof(PageEntry));
        }
        arr[ins].ptr    = ptr;
    // down by one. Order in both `entries` and `free_entries` IS load-bearing
    // because we binary-search both.
    static void page_table_remove_sorted_at(PageEntry *arr, u32 *len_p, u32 idx) {
        *len_p      -= 1u;
        u32 to_move  = *len_p - idx;
        u32 to_move  = *len_p - idx;
        if (to_move > 0u) {
            MemMove(&arr[idx], &arr[idx + 1u], (size)to_move * sizeof(PageEntry));
        }
    }
            return false;
        }
        PageEntry *arr = page->free_entries;
        u32        lo  = 0;
        u32        hi  = page->free_len;
        u32 to_move = page->free_len - ins;
        if (to_move > 0u) {
            MemMove(&arr[ins + 1u], &arr[ins], (size)to_move * sizeof(PageEntry));
        }
        arr[ins].ptr    = ptr;
Last updated on