aboutsummaryrefslogtreecommitdiff
path: root/src/kernel/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/core')
-rw-r--r--src/kernel/core/freemem.c10
-rw-r--r--src/kernel/core/kmalloc.c35
-rw-r--r--src/kernel/core/region.c14
-rw-r--r--src/kernel/core/thread.c9
4 files changed, 56 insertions, 12 deletions
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)