#include #include #include #include #include #include #include #define FREE_PAGE_MAGIC 0x50474d43 #define PAGE_MASK (PAGE_SIZE - 1) struct free_page { uint32_t magic; struct free_page *next; }; static uint8_t *pager_next = 0; static uint8_t *pager_limit = 0; static struct free_page *free_list = 0; static uint32_t spinlock = 0; void gilbraltar_pager_init(uintptr_t base, size_t size) { pager_next = (uint8_t *)((base + PAGE_SIZE - 1) & ~PAGE_MASK); pager_limit = (uint8_t *)((base + size) & ~PAGE_MASK); } size_t gilbraltar_pager_free_space(void) { return (pager_limit - pager_next); } void *gilbraltar_palloc(void) { assert(pager_next != 0); gilbraltar_spinlock_acquire(IRQ, &spinlock); gilbraltar_log(DEBUG, "Allocate a new page (actual: %08lx)\r\n", (uintptr_t)pager_next); struct free_page *free_page; if ((free_page = free_list) != 0) { assert(free_page->magic == FREE_PAGE_MAGIC); free_list = free_page->next; free_page->magic = 0; } else { free_page = (struct free_page *)pager_next; pager_next += PAGE_SIZE; if (pager_next > pager_limit) { gilbraltar_spinlock_release(IRQ, &spinlock); gilbraltar_log(ERROR, "Out of page.\r\n"); abort(); } } gilbraltar_log(DEBUG, "New page @ %08lx.\r\n", (uintptr_t)free_page); gilbraltar_spinlock_release(IRQ, &spinlock); return (free_page); } void gilbraltar_pager_free(void *page) { struct free_page *free_page = (struct free_page *)page; gilbraltar_spinlock_acquire(IRQ, &spinlock); free_page->magic = FREE_PAGE_MAGIC; free_page->next = free_list; free_list = free_page; gilbraltar_spinlock_release(IRQ, &spinlock); }