aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/kernel/Makefile3
-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
-rw-r--r--src/kernel/include/freemem.h7
-rw-r--r--src/kernel/include/kmalloc.h3
-rw-r--r--src/kernel/include/region.h4
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