diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/kernel/Makefile | 3 | ||||
-rw-r--r-- | src/kernel/core/freemem.c | 10 | ||||
-rw-r--r-- | src/kernel/core/kmalloc.c | 35 | ||||
-rw-r--r-- | src/kernel/core/region.c | 14 | ||||
-rw-r--r-- | src/kernel/core/thread.c | 9 | ||||
-rw-r--r-- | src/kernel/include/freemem.h | 7 | ||||
-rw-r--r-- | src/kernel/include/kmalloc.h | 3 | ||||
-rw-r--r-- | src/kernel/include/region.h | 4 |
8 files changed, 70 insertions, 15 deletions
diff --git a/src/kernel/Makefile b/src/kernel/Makefile index d6b973e..88a83e2 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -1,7 +1,8 @@ OBJ = core/loader.o core/dbglog.o \ core/gdt.o core/idt.o core/interrupt.o core/context_switch.o core/thread.o \ - core/frame.o core/paging.o core/region.o core/kmalloc.o core/worker.o \ + core/frame.o core/paging.o core/freemem.o core/region.o core/kmalloc.o \ + core/worker.o \ user/vfs.o user/nullfs.o user/process.o user/elf.o user/syscall.o \ dev/pci.o dev/pciide.o \ fs/iso9660.o diff --git a/src/kernel/core/freemem.c b/src/kernel/core/freemem.c new file mode 100644 index 0000000..153ec7a --- /dev/null +++ b/src/kernel/core/freemem.c @@ -0,0 +1,10 @@ +#include <freemem.h> +#include <thread.h> +#include <debug.h> + +void free_some_memory() { + dbg_printf("Currently out of memory ; free_some_memory not implemented. Waiting.\n"); + usleep(1000000); // Hope someone will do something... +} + +/* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/kernel/core/kmalloc.c b/src/kernel/core/kmalloc.c index e15572a..a8b115b 100644 --- a/src/kernel/core/kmalloc.c +++ b/src/kernel/core/kmalloc.c @@ -6,10 +6,30 @@ #include <frame.h> #include <paging.h> #include <region.h> +#include <freemem.h> static void* page_alloc_fun_for_kmalloc(size_t bytes) { - void* addr = region_alloc(bytes, "Core kernel heap", default_allocator_pf_handler); + void* addr = region_alloc(bytes, "Core kernel heap", pf_handler_unexpected); + if (addr == 0) return 0; + + // Map physical memory + for (void* i = addr; i < addr + bytes; i += PAGE_SIZE) { + int f = frame_alloc(1); + if (f == 0) goto failure; + if (!pd_map_page(i, f, true)) goto failure; + } + return addr; + +failure: + for (void* i = addr; i < addr + bytes; i += PAGE_SIZE) { + int f = pd_get_frame(i); + if (f != 0) { + pd_unmap_page(i); + frame_free(f, 1); + } + } + return 0; } static slab_type_t slab_sizes[] = { @@ -35,7 +55,7 @@ void kmalloc_setup() { region_free_unmap_free); } -void* malloc(size_t sz) { +static void* malloc0(size_t sz) { void* res = 0; mutex_lock(&malloc_mutex); @@ -45,6 +65,17 @@ void* malloc(size_t sz) { return res; } +void* malloc(size_t sz) { + void* res; + int tries = 0; + + while ((res = malloc0(sz)) == 0 && (tries++) < 3) { + free_some_memory(); + } + + return res; +} + void free(void* ptr) { mutex_lock(&malloc_mutex); slab_free(kernel_allocator, ptr); diff --git a/src/kernel/core/region.c b/src/kernel/core/region.c index c2c00a9..d22a98f 100644 --- a/src/kernel/core/region.c +++ b/src/kernel/core/region.c @@ -333,14 +333,14 @@ region_info_t *find_region(void* addr) { // HELPER FUNCTIONS : SIMPLE PF HANDLERS ; FREEING FUNCTIONS // // ========================================================= // -void default_allocator_pf_handler(pagedir_t *pd, struct region_info *r, void* addr) { - ASSERT(pd_get_frame(addr) == 0); // if error is of another type (RO, protected), we don't do anyting - - uint32_t f = frame_alloc(1); - if (f == 0) PANIC("Out Of Memory"); +void pf_handler_unexpected(pagedir_t *pd, struct region_info *r, void* addr) { + dbg_printf("Unexpected page fault at 0x%p\n", addr); + PANIC("Unexpected page fault"); +} - bool map_ok = pd_map_page(addr, f, 1); - if (!map_ok) PANIC("Could not map frame (OOM)"); +void pf_handler_stackoverflow(pagedir_t *pd, struct region_info *r, void* addr) { + dbg_printf("Kernel stack overflow at 0x%p\n", addr); + PANIC("Kernel stack overflow"); } void region_free_unmap_free(void* ptr) { diff --git a/src/kernel/core/thread.c b/src/kernel/core/thread.c index 5d2abae..cd46891 100644 --- a/src/kernel/core/thread.c +++ b/src/kernel/core/thread.c @@ -128,13 +128,15 @@ thread_t *new_thread(entry_t entry, void* data) { thread_t *t = (thread_t*)malloc(sizeof(thread_t)); if (t == 0) return 0; - void* stack = region_alloc(KPROC_STACK_SIZE, "Stack", 0); + void* stack = region_alloc(KPROC_STACK_SIZE + PAGE_SIZE, "Stack", pf_handler_stackoverflow); if (stack == 0) { free(t); return 0; } + void* stack_low = stack + PAGE_SIZE; + void* stack_high = stack_low + KPROC_STACK_SIZE; - for (void* i = stack + PAGE_SIZE; i < stack + KPROC_STACK_SIZE; i += PAGE_SIZE) { + for (void* i = stack_low; i < stack_high; i += PAGE_SIZE) { uint32_t f = frame_alloc(1); if (f == 0) { PANIC("TODO (OOM could not create kernel stack for new thread)"); @@ -146,8 +148,9 @@ thread_t *new_thread(entry_t entry, void* data) { } t->stack_region = find_region(stack); + ASSERT(stack_high == t->stack_region->addr + t->stack_region->size); - t->ctx.esp = (uint32_t*)(t->stack_region->addr + t->stack_region->size); + t->ctx.esp = (uint32_t*)stack_high; *(--t->ctx.esp) = (uint32_t)data; // push second argument : data *(--t->ctx.esp) = (uint32_t)entry; // push first argument : entry point *(--t->ctx.esp) = 0; // push invalid return address (the run_thread function never returns) diff --git a/src/kernel/include/freemem.h b/src/kernel/include/freemem.h new file mode 100644 index 0000000..d9c56a7 --- /dev/null +++ b/src/kernel/include/freemem.h @@ -0,0 +1,7 @@ +#pragma once + +#include <kmalloc.h> + +void free_some_memory(); // try to swap some pages and free some physical memory + +/* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/kernel/include/kmalloc.h b/src/kernel/include/kmalloc.h index d4a9272..17ea440 100644 --- a/src/kernel/include/kmalloc.h +++ b/src/kernel/include/kmalloc.h @@ -6,6 +6,9 @@ // Kernel memory allocator : one slab allocator for shared memory // Thread-safe. +// The normal malloc() call will try to free some memory when OOM and will loop +// a few times if it cannot. It may fail though. + void kmalloc_setup(); /* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/kernel/include/region.h b/src/kernel/include/region.h index a390e06..d5cba2d 100644 --- a/src/kernel/include/region.h +++ b/src/kernel/include/region.h @@ -24,8 +24,8 @@ region_info_t *find_region(void* addr); void region_free(void* addr); // some usefull PF handlers -// default_allocator_pf_handler : just allocates new frames on page faults -void default_allocator_pf_handler(pagedir_t *pd, struct region_info *r, void* addr); +void pf_handler_unexpected(pagedir_t *pd, struct region_info *r, void* addr); // Expects never to be called +void pf_handler_stackoverflow(pagedir_t *pd, struct region_info *r, void* addr); // Stack overflow detected // some functions for freeing regions and frames // region_free_unmap_free : deletes a region and frees all frames that were mapped in it |