mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
mm: refactor page.c related names to snake case
This commit is contained in:
@@ -238,7 +238,7 @@ static char *args[] = {
|
|||||||
static spinlock_t lock;
|
static spinlock_t lock;
|
||||||
DEFINE_KERNEL_ARGUMENT(global_syscall_logging, bool)
|
DEFINE_KERNEL_ARGUMENT(global_syscall_logging, bool)
|
||||||
#endif
|
#endif
|
||||||
extern size_t freepagecount;
|
extern size_t mm_free_page_count;
|
||||||
__attribute__((no_caller_saved_registers)) void arch_syscall_log(int syscall, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5, uint64_t a6) {
|
__attribute__((no_caller_saved_registers)) void arch_syscall_log(int syscall, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5, uint64_t a6) {
|
||||||
#ifdef SYSCALL_LOGGING
|
#ifdef SYSCALL_LOGGING
|
||||||
char argbuff[768];
|
char argbuff[768];
|
||||||
@@ -252,7 +252,7 @@ __attribute__((no_caller_saved_registers)) void arch_syscall_log(int syscall, ui
|
|||||||
arch_cpu_user_access_begin();
|
arch_cpu_user_access_begin();
|
||||||
snprintf(argbuff, 768, syscall < SYSCALL_COUNT ? args[syscall] : "N/A", a1, a2, a3, a4, a5, a6);
|
snprintf(argbuff, 768, syscall < SYSCALL_COUNT ? args[syscall] : "N/A", a1, a2, a3, a4, a5, a6);
|
||||||
arch_cpu_user_access_end();
|
arch_cpu_user_access_end();
|
||||||
snprintf(printbuff, 1024, "\e[92msyscall: pid %d tid %d: %s: %s (%lu cached pages, %lu free pages)\n\e[0m", proc->pid, thread->tid, syscall < SYSCALL_COUNT ? name[syscall] : "invalid syscall", argbuff, vmmcache_cachedpages, freepagecount);
|
snprintf(printbuff, 1024, "\e[92msyscall: pid %d tid %d: %s: %s (%lu cached pages, %lu free pages)\n\e[0m", proc->pid, thread->tid, syscall < SYSCALL_COUNT ? name[syscall] : "invalid syscall", argbuff, vmmcache_cachedpages, mm_free_page_count);
|
||||||
|
|
||||||
arch_interrupt_disable();
|
arch_interrupt_disable();
|
||||||
spinlock_acquire(&lock);
|
spinlock_acquire(&lock);
|
||||||
@@ -271,7 +271,7 @@ __attribute__((no_caller_saved_registers)) void arch_syscall_log_return(uint64_t
|
|||||||
if (!(proc->flags & PROC_FLAG_SYSTRACE) && GET_KERNEL_ARGUMENT(global_syscall_logging, bool) == false)
|
if (!(proc->flags & PROC_FLAG_SYSTRACE) && GET_KERNEL_ARGUMENT(global_syscall_logging, bool) == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
snprintf(printbuff, 1024, "\e[94msyscall return: pid %d tid %d: %lu %s (%lu cached pages, %lu free pages)\n\e[0m", proc->pid, thread->tid, ret, strerror(errno), vmmcache_cachedpages, freepagecount);
|
snprintf(printbuff, 1024, "\e[94msyscall return: pid %d tid %d: %lu %s (%lu cached pages, %lu free pages)\n\e[0m", proc->pid, thread->tid, ret, strerror(errno), vmmcache_cachedpages, mm_free_page_count);
|
||||||
arch_interrupt_disable();
|
arch_interrupt_disable();
|
||||||
spinlock_acquire(&lock);
|
spinlock_acquire(&lock);
|
||||||
LOGSTR(printbuff);
|
LOGSTR(printbuff);
|
||||||
|
|||||||
@@ -20,18 +20,18 @@
|
|||||||
typedef struct page_t {
|
typedef struct page_t {
|
||||||
struct vnode_t *backing;
|
struct vnode_t *backing;
|
||||||
uintmax_t offset;
|
uintmax_t offset;
|
||||||
struct page_t *hashnext;
|
struct page_t *hash_next;
|
||||||
struct page_t *hashprev;
|
struct page_t *hash_prev;
|
||||||
struct page_t *vnodenext;
|
struct page_t *vnode_next;
|
||||||
struct page_t *vnodeprev;
|
struct page_t *vnode_prev;
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
struct page_t *freenext;
|
struct page_t *free_next;
|
||||||
struct page_t *freeprev;
|
struct page_t *free_prev;
|
||||||
};
|
};
|
||||||
struct {
|
struct {
|
||||||
struct page_t *writenext;
|
struct page_t *write_next;
|
||||||
struct page_t *writeprev;
|
struct page_t *write_prev;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
uintmax_t refcount;
|
uintmax_t refcount;
|
||||||
@@ -49,9 +49,9 @@ void mm_release_range(void *addr, size_t size);
|
|||||||
void mm_page_init();
|
void mm_page_init();
|
||||||
void mm_get_page_statistics(size_t *total_pages, size_t *free_pages);
|
void mm_get_page_statistics(size_t *total_pages, size_t *free_pages);
|
||||||
|
|
||||||
extern uintptr_t hhdmbase;
|
extern uintptr_t hhdm_base;
|
||||||
|
|
||||||
#define MAKE_HHDM(x) (void *)((uintptr_t)x + hhdmbase)
|
#define MAKE_HHDM(x) (void *)((uintptr_t)x + hhdm_base)
|
||||||
#define FROM_HHDM(x) (void *)((uintptr_t)x - hhdmbase)
|
#define FROM_HHDM(x) (void *)((uintptr_t)x - hhdm_base)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+98
-98
@@ -8,21 +8,21 @@
|
|||||||
#include <kernel/vmmcache.h>
|
#include <kernel/vmmcache.h>
|
||||||
#include <kernel/init.h>
|
#include <kernel/init.h>
|
||||||
|
|
||||||
uintptr_t hhdmbase;
|
uintptr_t hhdm_base;
|
||||||
static size_t memorysize;
|
static size_t memory_size;
|
||||||
static size_t pagecount;
|
static size_t page_count;
|
||||||
size_t freepagecount;
|
size_t mm_free_page_count;
|
||||||
|
|
||||||
static mutex_t freelistmutex;
|
static mutex_t free_list_mutex;
|
||||||
static page_t *freelists[MEMORY_SECTION_COUNT];
|
static page_t *free_lists[MEMORY_SECTION_COUNT];
|
||||||
static page_t *freetails[MEMORY_SECTION_COUNT];
|
static page_t *free_tails[MEMORY_SECTION_COUNT];
|
||||||
static page_t *standbylists[MEMORY_SECTION_COUNT];
|
static page_t *standby_lists[MEMORY_SECTION_COUNT];
|
||||||
static page_t *standbytails[MEMORY_SECTION_COUNT];
|
static page_t *standby_tails[MEMORY_SECTION_COUNT];
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uintmax_t baseid;
|
uintmax_t base_id;
|
||||||
uintmax_t topid;
|
uintmax_t top_id;
|
||||||
uintmax_t searchstart;
|
uintmax_t search_start;
|
||||||
} section_t;
|
} section_t;
|
||||||
|
|
||||||
#define TOP_1MB (0x100000 / PAGE_SIZE)
|
#define TOP_1MB (0x100000 / PAGE_SIZE)
|
||||||
@@ -34,7 +34,7 @@ static section_t sections[MEMORY_SECTION_COUNT] = {
|
|||||||
{TOP_4GB, 0xffffffffffffffffl, TOP_4GB}
|
{TOP_4GB, 0xffffffffffffffffl, TOP_4GB}
|
||||||
};
|
};
|
||||||
|
|
||||||
static volatile struct limine_hhdm_request hhdmreq = {
|
static volatile struct limine_hhdm_request hhdm_req = {
|
||||||
.id = LIMINE_HHDM_REQUEST_ID,
|
.id = LIMINE_HHDM_REQUEST_ID,
|
||||||
.revision = 0
|
.revision = 0
|
||||||
};
|
};
|
||||||
@@ -46,81 +46,81 @@ volatile struct limine_memmap_request mm_page_limine_map = {
|
|||||||
|
|
||||||
static page_t* pages;
|
static page_t* pages;
|
||||||
|
|
||||||
#define PAGE_GETID(page) (((uintptr_t)(page) - (uintptr_t)pages) / sizeof(page_t))
|
#define PAGE_GET_ID(page) (((uintptr_t)(page) - (uintptr_t)pages) / sizeof(page_t))
|
||||||
#define PAGE_BOUNDARYCHECK(pageid) \
|
#define PAGE_BOUNDARY_CHECK(page_id) \
|
||||||
__assert((pageid) * PAGE_SIZE < (uintptr_t)pages || (pageid) * PAGE_SIZE >= (uintptr_t)&pages[pagecount])
|
__assert((page_id) * PAGE_SIZE < (uintptr_t)pages || (page_id) * PAGE_SIZE >= (uintptr_t)&pages[page_count])
|
||||||
|
|
||||||
static void insertinfreelist(page_t *page) {
|
static void insert_in_free_list(page_t *page) {
|
||||||
uintmax_t pageid = PAGE_GETID(page);
|
uintmax_t page_id = PAGE_GET_ID(page);
|
||||||
PAGE_BOUNDARYCHECK(pageid);
|
PAGE_BOUNDARY_CHECK(page_id);
|
||||||
struct page_t **list;
|
struct page_t **list;
|
||||||
struct page_t **tail;
|
struct page_t **tail;
|
||||||
|
|
||||||
int section;
|
int section;
|
||||||
|
|
||||||
if (pageid < TOP_1MB)
|
if (page_id < TOP_1MB)
|
||||||
section = MEMORY_SECTION_1MB;
|
section = MEMORY_SECTION_1MB;
|
||||||
else if (pageid < TOP_4GB)
|
else if (page_id < TOP_4GB)
|
||||||
section = MEMORY_SECTION_4GB;
|
section = MEMORY_SECTION_4GB;
|
||||||
else
|
else
|
||||||
section = MEMORY_SECTION_DEFAULT;
|
section = MEMORY_SECTION_DEFAULT;
|
||||||
|
|
||||||
list = page->backing ? &standbylists[section] : &freelists[section];
|
list = page->backing ? &standby_lists[section] : &free_lists[section];
|
||||||
tail = page->backing ? &standbytails[section] : &freetails[section];
|
tail = page->backing ? &standby_tails[section] : &free_tails[section];
|
||||||
|
|
||||||
if (sections[section].searchstart > pageid)
|
if (sections[section].search_start > page_id)
|
||||||
sections[section].searchstart = pageid;
|
sections[section].search_start = page_id;
|
||||||
|
|
||||||
page->freenext = *list;
|
page->free_next = *list;
|
||||||
page->freeprev = NULL;
|
page->free_prev = NULL;
|
||||||
*list = page;
|
*list = page;
|
||||||
if (page->freenext)
|
if (page->free_next)
|
||||||
page->freenext->freeprev = page;
|
page->free_next->free_prev = page;
|
||||||
else
|
else
|
||||||
*tail = page;
|
*tail = page;
|
||||||
|
|
||||||
++freepagecount;
|
++mm_free_page_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void removefromfreelist(page_t *page) {
|
static void remove_from_free_list(page_t *page) {
|
||||||
uintmax_t pageid = PAGE_GETID(page);
|
uintmax_t page_id = PAGE_GET_ID(page);
|
||||||
PAGE_BOUNDARYCHECK(pageid);
|
PAGE_BOUNDARY_CHECK(page_id);
|
||||||
struct page_t **list;
|
struct page_t **list;
|
||||||
struct page_t **tail;
|
struct page_t **tail;
|
||||||
|
|
||||||
int section;
|
int section;
|
||||||
|
|
||||||
if (pageid < TOP_1MB)
|
if (page_id < TOP_1MB)
|
||||||
section = MEMORY_SECTION_1MB;
|
section = MEMORY_SECTION_1MB;
|
||||||
else if (pageid < TOP_4GB)
|
else if (page_id < TOP_4GB)
|
||||||
section = MEMORY_SECTION_4GB;
|
section = MEMORY_SECTION_4GB;
|
||||||
else
|
else
|
||||||
section = MEMORY_SECTION_DEFAULT;
|
section = MEMORY_SECTION_DEFAULT;
|
||||||
|
|
||||||
list = page->backing ? &standbylists[section] : &freelists[section];
|
list = page->backing ? &standby_lists[section] : &free_lists[section];
|
||||||
tail = page->backing ? &standbytails[section] : &freetails[section];
|
tail = page->backing ? &standby_tails[section] : &free_tails[section];
|
||||||
|
|
||||||
if (page->freeprev)
|
if (page->free_prev)
|
||||||
page->freeprev->freenext = page->freenext;
|
page->free_prev->free_next = page->free_next;
|
||||||
else
|
else
|
||||||
*list = page->freenext;
|
*list = page->free_next;
|
||||||
|
|
||||||
if (page->freenext)
|
if (page->free_next)
|
||||||
page->freenext->freeprev = page->freeprev;
|
page->free_next->free_prev = page->free_prev;
|
||||||
else
|
else
|
||||||
*tail = page->freeprev;
|
*tail = page->free_prev;
|
||||||
|
|
||||||
page->freenext = NULL;
|
page->free_next = NULL;
|
||||||
page->freeprev = NULL;
|
page->free_prev = NULL;
|
||||||
|
|
||||||
--freepagecount;
|
--mm_free_page_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void internalhold(page_t *page) {
|
static void internal_hold(page_t *page) {
|
||||||
if (++page->refcount == 1) {
|
if (++page->refcount == 1) {
|
||||||
// this is only valid on standby pages, in case of free pages its an use after free
|
// this is only valid on standby pages, in case of free pages its an use after free
|
||||||
__assert((page->flags & PAGE_FLAGS_FREE) == 0);
|
__assert((page->flags & PAGE_FLAGS_FREE) == 0);
|
||||||
removefromfreelist(page);
|
remove_from_free_list(page);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,32 +129,32 @@ page_t *mm_get_page(void *address) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void *mm_get_page_address(page_t *page) {
|
void *mm_get_page_address(page_t *page) {
|
||||||
return (void *)(PAGE_GETID(page) * PAGE_SIZE);
|
return (void *)(PAGE_GET_ID(page) * PAGE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mm_hold_page(void *addr) {
|
void mm_hold_page(void *addr) {
|
||||||
page_t *page = &pages[((uintptr_t)addr / PAGE_SIZE)];
|
page_t *page = &pages[((uintptr_t)addr / PAGE_SIZE)];
|
||||||
|
|
||||||
MUTEX_ACQUIRE(&freelistmutex);
|
MUTEX_ACQUIRE(&free_list_mutex);
|
||||||
internalhold(page);
|
internal_hold(page);
|
||||||
MUTEX_RELEASE(&freelistmutex);
|
MUTEX_RELEASE(&free_list_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mm_release_page(void *addr) {
|
void mm_release_page(void *addr) {
|
||||||
page_t *page = &pages[(uintptr_t)addr / PAGE_SIZE];
|
page_t *page = &pages[(uintptr_t)addr / PAGE_SIZE];
|
||||||
|
|
||||||
MUTEX_ACQUIRE(&freelistmutex);
|
MUTEX_ACQUIRE(&free_list_mutex);
|
||||||
__assert(page->refcount != 0);
|
__assert(page->refcount != 0);
|
||||||
if (--page->refcount == 0) {
|
if (--page->refcount == 0) {
|
||||||
__assert((page->flags & PAGE_FLAGS_DIRTY) == 0);
|
__assert((page->flags & PAGE_FLAGS_DIRTY) == 0);
|
||||||
insertinfreelist(page);
|
insert_in_free_list(page);
|
||||||
if (page->backing == NULL)
|
if (page->backing == NULL)
|
||||||
page->flags |= PAGE_FLAGS_FREE;
|
page->flags |= PAGE_FLAGS_FREE;
|
||||||
}
|
}
|
||||||
MUTEX_RELEASE(&freelistmutex);
|
MUTEX_RELEASE(&free_list_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void doalloc(page_t *page) {
|
static void do_alloc(page_t *page) {
|
||||||
__assert(page->refcount == 0);
|
__assert(page->refcount == 0);
|
||||||
memset(page, 0, sizeof(page_t));
|
memset(page, 0, sizeof(page_t));
|
||||||
page->refcount = 1;
|
page->refcount = 1;
|
||||||
@@ -162,74 +162,74 @@ static void doalloc(page_t *page) {
|
|||||||
|
|
||||||
void *mm_alloc_page(int section) {
|
void *mm_alloc_page(int section) {
|
||||||
retry:
|
retry:
|
||||||
MUTEX_ACQUIRE(&freelistmutex);
|
MUTEX_ACQUIRE(&free_list_mutex);
|
||||||
page_t *page = NULL;
|
page_t *page = NULL;
|
||||||
|
|
||||||
// try to take a free anonymous page
|
// try to take a free anonymous page
|
||||||
for (int i = section; i >= 0; --i) {
|
for (int i = section; i >= 0; --i) {
|
||||||
page = freelists[i];
|
page = free_lists[i];
|
||||||
if (page) {
|
if (page) {
|
||||||
removefromfreelist(page);
|
remove_from_free_list(page);
|
||||||
__assert(page->refcount == 0);
|
__assert(page->refcount == 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cachepage = false;
|
bool cache_page = false;
|
||||||
|
|
||||||
// if that wasn't possible, try to take from the cache standby list
|
// if that wasn't possible, try to take from the cache standby list
|
||||||
if (page == NULL) {
|
if (page == NULL) {
|
||||||
for (int i = section; i >= 0; --i) {
|
for (int i = section; i >= 0; --i) {
|
||||||
page = standbytails[i];
|
page = standby_tails[i];
|
||||||
if (page) {
|
if (page) {
|
||||||
cachepage = true;
|
cache_page = true;
|
||||||
internalhold(page);
|
internal_hold(page);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MUTEX_RELEASE(&freelistmutex);
|
MUTEX_RELEASE(&free_list_mutex);
|
||||||
|
|
||||||
if (cachepage && vmmcache_takepage(page) == EAGAIN) {
|
if (cache_page && vmmcache_takepage(page) == EAGAIN) {
|
||||||
// someone already got the page from the cache between us holding it and taking it
|
// someone already got the page from the cache between us holding it and taking it
|
||||||
mm_release_page(mm_get_page_address(page));
|
mm_release_page(mm_get_page_address(page));
|
||||||
page = NULL;
|
page = NULL;
|
||||||
// retry it from the start, as an anonymous page could have been released while the lock was not held
|
// retry it from the start, as an anonymous page could have been released while the lock was not held
|
||||||
goto retry;
|
goto retry;
|
||||||
} else if (cachepage) {
|
} else if (cache_page) {
|
||||||
// we got the page from the cache, all is good and we hold the only reference to it.
|
// we got the page from the cache, all is good and we hold the only reference to it.
|
||||||
// set the refcount to 0, as expected by the doalloc call
|
// set the refcount to 0, as expected by the do_alloc call
|
||||||
page->refcount = 0;
|
page->refcount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *address = NULL;
|
void *address = NULL;
|
||||||
if (page) {
|
if (page) {
|
||||||
address = (void *)(PAGE_GETID(page) * PAGE_SIZE);
|
address = (void *)(PAGE_GET_ID(page) * PAGE_SIZE);
|
||||||
doalloc(page);
|
do_alloc(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mm_force_free_page(void *address, size_t count) {
|
void mm_force_free_page(void *address, size_t count) {
|
||||||
MUTEX_ACQUIRE(&freelistmutex);
|
MUTEX_ACQUIRE(&free_list_mutex);
|
||||||
memorysize += PAGE_SIZE * count;
|
memory_size += PAGE_SIZE * count;
|
||||||
__assert(((uintptr_t)address % PAGE_SIZE) == 0);
|
__assert(((uintptr_t)address % PAGE_SIZE) == 0);
|
||||||
uintmax_t baseid = (uintptr_t)address / PAGE_SIZE;
|
uintmax_t base_id = (uintptr_t)address / PAGE_SIZE;
|
||||||
for (int i = 0; i < count; ++i) {
|
for (int i = 0; i < count; ++i) {
|
||||||
uintmax_t pageid = baseid + i;
|
uintmax_t page_id = base_id + i;
|
||||||
PAGE_BOUNDARYCHECK(pageid);
|
PAGE_BOUNDARY_CHECK(page_id);
|
||||||
page_t *page = &pages[pageid];
|
page_t *page = &pages[page_id];
|
||||||
page->flags |= PAGE_FLAGS_FREE;
|
page->flags |= PAGE_FLAGS_FREE;
|
||||||
insertinfreelist(page);
|
insert_in_free_list(page);
|
||||||
}
|
}
|
||||||
MUTEX_RELEASE(&freelistmutex);
|
MUTEX_RELEASE(&free_list_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mm_page_init() {
|
void mm_page_init() {
|
||||||
__assert(hhdmreq.response);
|
__assert(hhdm_req.response);
|
||||||
hhdmbase = hhdmreq.response->offset;
|
hhdm_base = hhdm_req.response->offset;
|
||||||
__assert(mm_page_limine_map.response);
|
__assert(mm_page_limine_map.response);
|
||||||
|
|
||||||
// get size of memory, top of usable memory, biggest section and print memory map
|
// get size of memory, top of usable memory, biggest section and print memory map
|
||||||
@@ -240,30 +240,30 @@ void mm_page_init() {
|
|||||||
struct limine_memmap_entry *e = mm_page_limine_map.response->entries[i];
|
struct limine_memmap_entry *e = mm_page_limine_map.response->entries[i];
|
||||||
printf("mm: %016p -> %016p: %d\n", e->base, e->base + e->length, e->type);
|
printf("mm: %016p -> %016p: %d\n", e->base, e->base + e->length, e->type);
|
||||||
if (e->type == LIMINE_MEMMAP_USABLE || e->type == LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE || e->type == LIMINE_MEMMAP_EXECUTABLE_AND_MODULES) {
|
if (e->type == LIMINE_MEMMAP_USABLE || e->type == LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE || e->type == LIMINE_MEMMAP_EXECUTABLE_AND_MODULES) {
|
||||||
size_t sectiontop = e->base + e->length;
|
size_t section_top = e->base + e->length;
|
||||||
if (sectiontop > top)
|
if (section_top > top)
|
||||||
top = sectiontop;
|
top = section_top;
|
||||||
}
|
}
|
||||||
if (e->type == LIMINE_MEMMAP_USABLE) {
|
if (e->type == LIMINE_MEMMAP_USABLE) {
|
||||||
if (biggest == NULL || e->length > biggest->length)
|
if (biggest == NULL || e->length > biggest->length)
|
||||||
biggest = e;
|
biggest = e;
|
||||||
memorysize += e->length;
|
memory_size += e->length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pages = MAKE_HHDM((page_t *)biggest->base);
|
pages = MAKE_HHDM((page_t *)biggest->base);
|
||||||
pagecount = ROUND_UP(top, PAGE_SIZE) / PAGE_SIZE;
|
page_count = ROUND_UP(top, PAGE_SIZE) / PAGE_SIZE;
|
||||||
memset(pages, 0, pagecount * sizeof(page_t));
|
memset(pages, 0, page_count * sizeof(page_t));
|
||||||
printf("mm: %d pages used for page list\n", ROUND_UP(pagecount * sizeof(page_t), PAGE_SIZE) / PAGE_SIZE);
|
printf("mm: %d pages used for page list\n", ROUND_UP(page_count * sizeof(page_t), PAGE_SIZE) / PAGE_SIZE);
|
||||||
|
|
||||||
// initialize usable memory
|
// initialize usable memory
|
||||||
for (size_t i = 0; i < mm_page_limine_map.response->entry_count; ++i) {
|
for (size_t i = 0; i < mm_page_limine_map.response->entry_count; ++i) {
|
||||||
struct limine_memmap_entry *e = mm_page_limine_map.response->entries[i];
|
struct limine_memmap_entry *e = mm_page_limine_map.response->entries[i];
|
||||||
if (e->type == LIMINE_MEMMAP_USABLE) {
|
if (e->type == LIMINE_MEMMAP_USABLE) {
|
||||||
int firstusablepage = e == biggest ? ROUND_UP(e->base + pagecount * sizeof(page_t), PAGE_SIZE) / PAGE_SIZE : e->base / PAGE_SIZE;
|
int first_usable_page = e == biggest ? ROUND_UP(e->base + page_count * sizeof(page_t), PAGE_SIZE) / PAGE_SIZE : e->base / PAGE_SIZE;
|
||||||
for (int i = firstusablepage; i < (e->base + e->length) / PAGE_SIZE; ++i) {
|
for (int i = first_usable_page; i < (e->base + e->length) / PAGE_SIZE; ++i) {
|
||||||
pages[i].flags |= PAGE_FLAGS_FREE;
|
pages[i].flags |= PAGE_FLAGS_FREE;
|
||||||
insertinfreelist(&pages[i]);
|
insert_in_free_list(&pages[i]);
|
||||||
}
|
}
|
||||||
} else if (e->type == LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE) {
|
} else if (e->type == LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE) {
|
||||||
for (int i = 0; i < e->length / PAGE_SIZE; ++i) {
|
for (int i = 0; i < e->length / PAGE_SIZE; ++i) {
|
||||||
@@ -273,7 +273,7 @@ void mm_page_init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MUTEX_INIT(&freelistmutex);
|
MUTEX_INIT(&free_list_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
INIT_ROUTINE_DEFINE(mm_page, INIT_ROUTINE_FLAGS_NONE, mm_page_init, arch_early);
|
INIT_ROUTINE_DEFINE(mm_page, INIT_ROUTINE_FLAGS_NONE, mm_page_init, arch_early);
|
||||||
@@ -286,14 +286,14 @@ void *mm_alloc_pages(size_t size, int section) {
|
|||||||
if (size == 1)
|
if (size == 1)
|
||||||
return mm_alloc_page(section);
|
return mm_alloc_page(section);
|
||||||
|
|
||||||
MUTEX_ACQUIRE(&freelistmutex);
|
MUTEX_ACQUIRE(&free_list_mutex);
|
||||||
|
|
||||||
uintmax_t page = 0;
|
uintmax_t page = 0;
|
||||||
size_t found = 0;
|
size_t found = 0;
|
||||||
|
|
||||||
for (; section >= 0; --section) {
|
for (; section >= 0; --section) {
|
||||||
for (page = sections[section].searchstart; page < sections[section].topid; ++page) {
|
for (page = sections[section].search_start; page < sections[section].top_id; ++page) {
|
||||||
if (page >= pagecount)
|
if (page >= page_count)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (pages[page].flags & PAGE_FLAGS_FREE) {
|
if (pages[page].flags & PAGE_FLAGS_FREE) {
|
||||||
@@ -313,12 +313,12 @@ void *mm_alloc_pages(size_t size, int section) {
|
|||||||
page = page - (found - 1);
|
page = page - (found - 1);
|
||||||
addr = (void *)(page * PAGE_SIZE);
|
addr = (void *)(page * PAGE_SIZE);
|
||||||
for (int i = 0; i < size; ++i) {
|
for (int i = 0; i < size; ++i) {
|
||||||
removefromfreelist(&pages[page + i]);
|
remove_from_free_list(&pages[page + i]);
|
||||||
doalloc(&pages[page + i]);
|
do_alloc(&pages[page + i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MUTEX_RELEASE(&freelistmutex);
|
MUTEX_RELEASE(&free_list_mutex);
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -331,6 +331,6 @@ void mm_release_range(void *addr, size_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void mm_get_page_statistics(size_t *total_pages, size_t *free_pages) {
|
void mm_get_page_statistics(size_t *total_pages, size_t *free_pages) {
|
||||||
*total_pages = memorysize / PAGE_SIZE;
|
*total_pages = memory_size / PAGE_SIZE;
|
||||||
*free_pages = freepagecount;
|
*free_pages = mm_free_page_count;
|
||||||
}
|
}
|
||||||
|
|||||||
+41
-41
@@ -45,7 +45,7 @@ static page_t *findpage(vnode_t *vnode, uintmax_t offset) {
|
|||||||
while (page) {
|
while (page) {
|
||||||
if (page->backing == vnode && page->offset == offset)
|
if (page->backing == vnode && page->offset == offset)
|
||||||
break;
|
break;
|
||||||
page = page->hashnext;
|
page = page->hash_next;
|
||||||
}
|
}
|
||||||
|
|
||||||
return page;
|
return page;
|
||||||
@@ -55,19 +55,19 @@ static page_t *findpage(vnode_t *vnode, uintmax_t offset) {
|
|||||||
static void putpage(page_t *page) {
|
static void putpage(page_t *page) {
|
||||||
uintmax_t entry = getentry(page->backing, page->offset);
|
uintmax_t entry = getentry(page->backing, page->offset);
|
||||||
// add to table list
|
// add to table list
|
||||||
page->hashprev = NULL;
|
page->hash_prev = NULL;
|
||||||
page->hashnext = table[entry];
|
page->hash_next = table[entry];
|
||||||
if (table[entry])
|
if (table[entry])
|
||||||
table[entry]->hashprev = page;
|
table[entry]->hash_prev = page;
|
||||||
|
|
||||||
table[entry] = page;
|
table[entry] = page;
|
||||||
|
|
||||||
// add to vnode list
|
// add to vnode list
|
||||||
// XXX this could be a bit slow if a large portion of the file is in memory and it gets purged
|
// XXX this could be a bit slow if a large portion of the file is in memory and it gets purged
|
||||||
page->vnodeprev = NULL;
|
page->vnode_prev = NULL;
|
||||||
page->vnodenext = page->backing->pages;
|
page->vnode_next = page->backing->pages;
|
||||||
if (page->backing->pages)
|
if (page->backing->pages)
|
||||||
page->backing->pages->vnodeprev = page;
|
page->backing->pages->vnode_prev = page;
|
||||||
|
|
||||||
page->backing->pages = page;
|
page->backing->pages = page;
|
||||||
++vmmcache_cachedpages;
|
++vmmcache_cachedpages;
|
||||||
@@ -78,28 +78,28 @@ static void removepage(page_t *page) {
|
|||||||
uintmax_t entry = getentry(page->backing, page->offset);
|
uintmax_t entry = getentry(page->backing, page->offset);
|
||||||
|
|
||||||
// remove from table list
|
// remove from table list
|
||||||
if (page->hashnext)
|
if (page->hash_next)
|
||||||
page->hashnext->hashprev = page->hashprev;
|
page->hash_next->hash_prev = page->hash_prev;
|
||||||
|
|
||||||
if (page->hashprev)
|
if (page->hash_prev)
|
||||||
page->hashprev->hashnext = page->hashnext;
|
page->hash_prev->hash_next = page->hash_next;
|
||||||
else
|
else
|
||||||
table[entry] = page->hashnext;
|
table[entry] = page->hash_next;
|
||||||
|
|
||||||
page->hashnext = NULL;
|
page->hash_next = NULL;
|
||||||
page->hashprev = NULL;
|
page->hash_prev = NULL;
|
||||||
|
|
||||||
// remove from vnode list
|
// remove from vnode list
|
||||||
if (page->vnodenext)
|
if (page->vnode_next)
|
||||||
page->vnodenext->vnodeprev = page->vnodeprev;
|
page->vnode_next->vnode_prev = page->vnode_prev;
|
||||||
|
|
||||||
if (page->vnodeprev)
|
if (page->vnode_prev)
|
||||||
page->vnodeprev->vnodenext = page->vnodenext;
|
page->vnode_prev->vnode_next = page->vnode_next;
|
||||||
else
|
else
|
||||||
page->backing->pages = page->vnodenext;
|
page->backing->pages = page->vnode_next;
|
||||||
|
|
||||||
page->vnodenext = NULL;
|
page->vnode_next = NULL;
|
||||||
page->vnodeprev = NULL;
|
page->vnode_prev = NULL;
|
||||||
--vmmcache_cachedpages;
|
--vmmcache_cachedpages;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,7 +270,7 @@ int vmmcache_truncate(vnode_t *vnode, uintmax_t offset) {
|
|||||||
|
|
||||||
while (page) {
|
while (page) {
|
||||||
page_t *oldpage = page;
|
page_t *oldpage = page;
|
||||||
page = page->vnodenext;
|
page = page->vnode_next;
|
||||||
|
|
||||||
// only truncate past a certain offset
|
// only truncate past a certain offset
|
||||||
if (oldpage->offset < offset)
|
if (oldpage->offset < offset)
|
||||||
@@ -278,7 +278,7 @@ int vmmcache_truncate(vnode_t *vnode, uintmax_t offset) {
|
|||||||
|
|
||||||
oldpage->flags |= PAGE_FLAGS_TRUNCATED;
|
oldpage->flags |= PAGE_FLAGS_TRUNCATED;
|
||||||
removepage(oldpage);
|
removepage(oldpage);
|
||||||
oldpage->vnodenext = pagelist;
|
oldpage->vnode_next = pagelist;
|
||||||
pagelist = oldpage;
|
pagelist = oldpage;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,7 +287,7 @@ int vmmcache_truncate(vnode_t *vnode, uintmax_t offset) {
|
|||||||
// make sure to unref if they are pinned
|
// make sure to unref if they are pinned
|
||||||
while (pagelist) {
|
while (pagelist) {
|
||||||
page_t *page = pagelist;
|
page_t *page = pagelist;
|
||||||
pagelist = pagelist->vnodenext;
|
pagelist = pagelist->vnode_next;
|
||||||
if (page->flags & PAGE_FLAGS_PINNED)
|
if (page->flags & PAGE_FLAGS_PINNED)
|
||||||
mm_release_page(mm_get_page_address(page));
|
mm_release_page(mm_get_page_address(page));
|
||||||
}
|
}
|
||||||
@@ -337,24 +337,24 @@ int vmmcache_syncvnode(vnode_t *vnode, uintmax_t offset, size_t size) {
|
|||||||
// TODO create a proper vnode dirty list as to not have to loop through the ENTIRE thing in memory
|
// TODO create a proper vnode dirty list as to not have to loop through the ENTIRE thing in memory
|
||||||
page_t *page = vnode->pages;
|
page_t *page = vnode->pages;
|
||||||
page_t *vnodedirtylist = NULL;
|
page_t *vnodedirtylist = NULL;
|
||||||
for (; page; page = page->vnodenext) {
|
for (; page; page = page->vnode_next) {
|
||||||
if (page->offset < offset || page->offset >= top || (page->flags & PAGE_FLAGS_DIRTY) == 0 || (page->flags & PAGE_FLAGS_VNODE_SYNCING))
|
if (page->offset < offset || page->offset >= top || (page->flags & PAGE_FLAGS_DIRTY) == 0 || (page->flags & PAGE_FLAGS_VNODE_SYNCING))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// remove from write list and add to an internal list using the write pointers
|
// remove from write list and add to an internal list using the write pointers
|
||||||
// in a singly linked list way
|
// in a singly linked list way
|
||||||
if (page->writenext)
|
if (page->write_next)
|
||||||
page->writenext->writeprev = page->writeprev;
|
page->write_next->write_prev = page->write_prev;
|
||||||
else
|
else
|
||||||
dirtylistend = page->writeprev;
|
dirtylistend = page->write_prev;
|
||||||
|
|
||||||
if (page->writeprev)
|
if (page->write_prev)
|
||||||
page->writeprev->writenext = page->writenext;
|
page->write_prev->write_next = page->write_next;
|
||||||
else
|
else
|
||||||
dirtylist = page->writenext;
|
dirtylist = page->write_next;
|
||||||
|
|
||||||
page->writenext = vnodedirtylist;
|
page->write_next = vnodedirtylist;
|
||||||
page->writeprev = NULL;
|
page->write_prev = NULL;
|
||||||
page->flags |= PAGE_FLAGS_VNODE_SYNCING;
|
page->flags |= PAGE_FLAGS_VNODE_SYNCING;
|
||||||
vnodedirtylist = page;
|
vnodedirtylist = page;
|
||||||
}
|
}
|
||||||
@@ -367,8 +367,8 @@ int vmmcache_syncvnode(vnode_t *vnode, uintmax_t offset, size_t size) {
|
|||||||
// retry the write and keep on syncing the pages to disk
|
// retry the write and keep on syncing the pages to disk
|
||||||
HOLD_LOCK();
|
HOLD_LOCK();
|
||||||
page_t *page = vnodedirtylist;
|
page_t *page = vnodedirtylist;
|
||||||
vnodedirtylist = vnodedirtylist->writenext;
|
vnodedirtylist = vnodedirtylist->write_next;
|
||||||
page->writenext = NULL;
|
page->write_next = NULL;
|
||||||
page->flags &= ~PAGE_FLAGS_VNODE_SYNCING;
|
page->flags &= ~PAGE_FLAGS_VNODE_SYNCING;
|
||||||
|
|
||||||
// another thread could already have synced this page, verify if it is still dirty
|
// another thread could already have synced this page, verify if it is still dirty
|
||||||
@@ -417,10 +417,10 @@ int vmmcache_makedirty(page_t *page) {
|
|||||||
page->flags |= PAGE_FLAGS_DIRTY;
|
page->flags |= PAGE_FLAGS_DIRTY;
|
||||||
|
|
||||||
if ((page->flags & PAGE_FLAGS_VNODE_SYNCING) == 0) {
|
if ((page->flags & PAGE_FLAGS_VNODE_SYNCING) == 0) {
|
||||||
page->writeprev = NULL;
|
page->write_prev = NULL;
|
||||||
page->writenext = dirtylist;
|
page->write_next = dirtylist;
|
||||||
if (dirtylist)
|
if (dirtylist)
|
||||||
dirtylist->writeprev = page;
|
dirtylist->write_prev = page;
|
||||||
else
|
else
|
||||||
dirtylistend = page;
|
dirtylistend = page;
|
||||||
|
|
||||||
@@ -461,13 +461,13 @@ static void writer() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
dirtylistend = page->writeprev;
|
dirtylistend = page->write_prev;
|
||||||
if (dirtylistend)
|
if (dirtylistend)
|
||||||
dirtylistend->writenext = NULL;
|
dirtylistend->write_next = NULL;
|
||||||
else
|
else
|
||||||
dirtylist = NULL;
|
dirtylist = NULL;
|
||||||
|
|
||||||
page->writeprev = NULL;
|
page->write_prev = NULL;
|
||||||
// TODO notify error on vmmcache_syncvnode
|
// TODO notify error on vmmcache_syncvnode
|
||||||
syncpage((page_t *)page, true);
|
syncpage((page_t *)page, true);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user