summaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
authorAlex AUVOLAT <alexis211@gmail.com>2012-05-01 17:42:36 +0200
committerAlex AUVOLAT <alexis211@gmail.com>2012-05-01 17:42:36 +0200
commite9683297bf480f9590b0e5796f4520fb430e2e03 (patch)
tree93ef75cd154edf4c342d0a22cd56eb3670feb2b5 /src/kernel
parente8cf65c07d78e3cfbac953b1b97c51998a5900df (diff)
downloadTCE-e9683297bf480f9590b0e5796f4520fb430e2e03.tar.gz
TCE-e9683297bf480f9590b0e5796f4520fb430e2e03.zip
Now using Doug Lea's malloc for userland too. And improved stability.
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/Makefile4
-rw-r--r--src/kernel/core/kmain.c7
-rw-r--r--src/kernel/core/sys.c3
-rw-r--r--src/kernel/core/test.c37
-rw-r--r--src/kernel/core/test.h6
-rw-r--r--src/kernel/lib/mutex.c24
-rw-r--r--src/kernel/lib/mutex.h15
-rw-r--r--src/kernel/linker/elf.c9
-rw-r--r--src/kernel/mem/_dlmalloc.c8
-rw-r--r--src/kernel/mem/_dlmalloc.h5
-rw-r--r--src/kernel/mem/gdt.c2
-rw-r--r--src/kernel/mem/mem.h1
-rw-r--r--src/kernel/mem/paging.c5
-rw-r--r--src/kernel/task/idt.c6
-rw-r--r--src/kernel/task/sched.c2
-rw-r--r--src/kernel/task/syscall.c8
-rw-r--r--src/kernel/task/task.c66
-rw-r--r--src/kernel/task/task.h19
18 files changed, 106 insertions, 121 deletions
diff --git a/src/kernel/Makefile b/src/kernel/Makefile
index 0950ba7..6060911 100644
--- a/src/kernel/Makefile
+++ b/src/kernel/Makefile
@@ -1,8 +1,8 @@
Out = kernel.elf
-Obj = core/loader_.o core/kmain.o core/sys.o core/test.o \
+Obj = core/loader_.o core/kmain.o core/sys.o \
core/monitor.o task/timer.o \
task/idt.o task/idt_.o task/task.o task/task_.o task/syscall.o task/sched.o \
- lib/bitset.o lib/mutex.o lib/std.o \
+ lib/bitset.o lib/std.o \
mem/mem.o mem/paging.o mem/gdt.o mem/_dlmalloc.o mem/seg.o \
linker/elf.o
diff --git a/src/kernel/core/kmain.c b/src/kernel/core/kmain.c
index 17c9425..8c36b54 100644
--- a/src/kernel/core/kmain.c
+++ b/src/kernel/core/kmain.c
@@ -4,7 +4,6 @@
#include "multiboot.h"
#include "monitor.h"
#include "sys.h"
-#include "test.h"
#include <task/idt.h>
#include <task/timer.h>
#include <task/task.h>
@@ -56,8 +55,6 @@ void kmain(struct multiboot_info_t* mbd, int32_t magic) {
//kheap_init();
timer_init(30);
tasking_init();
-
- //test_run();
monitor_write("\n\nLoading modules :\n");
for (i = 0; i < mbd->mods_count; i++) {
@@ -66,7 +63,7 @@ void kmain(struct multiboot_info_t* mbd, int32_t magic) {
if (elf_check((uint8_t*)mods[i].mod_start)) {
monitor_write(" : Invalid ELF file\n");
} else {
- struct process *pr = elf_exec((uint8_t*)mods[i].mod_start, PL_DRIVER);
+ struct process *pr = elf_exec((uint8_t*)mods[i].mod_start, PL_USER);
if (pr == 0) {
monitor_write(" : Error loading\n");
} else {
@@ -77,6 +74,6 @@ void kmain(struct multiboot_info_t* mbd, int32_t magic) {
monitor_write("Modules now RULE THE WORLD !\n\n");
sti();
- tasking_switch();
+ schedule();
PANIC("Should never happen. Something probably went wrong with multitasking.");
}
diff --git a/src/kernel/core/sys.c b/src/kernel/core/sys.c
index 4a88838..2c2372d 100644
--- a/src/kernel/core/sys.c
+++ b/src/kernel/core/sys.c
@@ -39,11 +39,12 @@ void stack_trace(size_t bp) {
/* For internal use only. Used by panic and panic_assert. */
static void panic_do(char* file, int line) {
+ asm volatile("cli;");
monitor_write("\n File:\t\t"); monitor_write(file); monitor_put(':'); monitor_writeDec(line);
monitor_write("\nTrace:\n");
size_t bp; asm volatile("mov %%ebp,%0" : "=r"(bp)); stack_trace(bp);
monitor_write("\n\t\tSystem halted -_-'");
- asm volatile("cli; hlt");
+ asm volatile("hlt");
}
/* These functions stop the system, reporting an error message, because something bad happenned. */
diff --git a/src/kernel/core/test.c b/src/kernel/core/test.c
deleted file mode 100644
index 8f7b32c..0000000
--- a/src/kernel/core/test.c
+++ /dev/null
@@ -1,37 +0,0 @@
-#include "test.h"
-#include "monitor.h"
-#include <mem/mem.h>
-#include "sys.h"
-
-static void test_run_kmalloc() {
- monitor_write("\tkmalloc:\n");
- int alloc_sizes[8] = { 10, 32, 16, 20, 64, 128, 32, 48 };
- int *ptrs[8] = { 0 };
- int t, i;
- for (t = 0; t < 4; t++) {
- for (i = 0; i < 8; i++) {
- monitor_writeDec(i); monitor_write(" alloc "); monitor_writeDec(alloc_sizes[i]);
- monitor_write(" : ");
- ptrs[i] = kmalloc(alloc_sizes[i]);
- ASSERT(ptrs[i] != 0);
- *ptrs[i] = i;
- monitor_writeHex((int)ptrs[i]); monitor_write("\n");
- }
- monitor_write("free : ");
- for (i = 0; i < 8; i++) {
- monitor_writeDec(i);
- ASSERT(*ptrs[i] == i);
- kfree(ptrs[i]);
- monitor_write(".");
- }
- monitor_write("\n");
- }
-}
-
-/* This function is called when the kernel starts up.
- It runs some basic unit tests (for the moment, only tests kmalloc/kfree) */
-void test_run() {
- monitor_write("Unit tests:\n");
- test_run_kmalloc();
- monitor_write(" >> Tests OK\n");
-}
diff --git a/src/kernel/core/test.h b/src/kernel/core/test.h
deleted file mode 100644
index ee689c6..0000000
--- a/src/kernel/core/test.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef DEF_TEST_H
-#define DEF_TEST_H
-
-void test_run(); //run basic unit tests on kmalloc() and kfree()
-
-#endif
diff --git a/src/kernel/lib/mutex.c b/src/kernel/lib/mutex.c
deleted file mode 100644
index 2664eb0..0000000
--- a/src/kernel/lib/mutex.c
+++ /dev/null
@@ -1,24 +0,0 @@
-#include "mutex.h"
-#include <task/task.h>
-
-/* Internal use only. This function is atomic, meaning it cannot be interrupted by a system task switch. */
-static uint32_t atomic_exchange(uint32_t* ptr, uint32_t newval) {
- uint32_t r;
- asm volatile("xchg (%%ecx), %%eax" : "=a"(r) : "c"(ptr), "a"(newval));
- return r;
-}
-
-void mutex_lock(uint32_t* mutex) {
- while (atomic_exchange(mutex, MUTEX_LOCKED) == MUTEX_LOCKED) {
- thread_sleep(1);
- }
-}
-
-int mutex_lockE(uint32_t* mutex) {
- if (atomic_exchange(mutex, MUTEX_LOCKED) == MUTEX_LOCKED) return 0;
- return 1;
-}
-
-void mutex_unlock(uint32_t* mutex) {
- *mutex = MUTEX_UNLOCKED;
-}
diff --git a/src/kernel/lib/mutex.h b/src/kernel/lib/mutex.h
deleted file mode 100644
index 2687b30..0000000
--- a/src/kernel/lib/mutex.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef DEF_MUTEX_H
-#define DEF_MUTEX_H
-
-#include <types.h>
-
-#define MUTEX_LOCKED 1
-#define MUTEX_UNLOCKED 0
-
-//A mutex is just an uint32_t
-
-void mutex_lock(uint32_t* mutex); //wait for mutex to be free
-int mutex_lockE(uint32_t* mutex); //lock mutex only if free, returns !0 if locked, 0 if was busy
-void mutex_unlock(uint32_t* mutex);
-
-#endif
diff --git a/src/kernel/linker/elf.c b/src/kernel/linker/elf.c
index 7eaae94..af6d057 100644
--- a/src/kernel/linker/elf.c
+++ b/src/kernel/linker/elf.c
@@ -1,7 +1,7 @@
#include "elf.h"
#include <mem/paging.h>
#include <mem/seg.h>
-#include <stdlib.h>
+#include <stdlib_common.h>
#include <core/sys.h>
int elf_check(uint8_t *data) {
@@ -14,6 +14,7 @@ thread_entry elf_load(uint8_t *data, struct process* process) {
struct elf_ehdr *ehdr = (struct elf_ehdr*)data;
struct elf_phdr *phdr;
int i;
+ size_t dataseg = 0;
if (elf_check(data)) return 0;
struct page_directory *r = current_pagedir;
@@ -28,9 +29,15 @@ thread_entry elf_load(uint8_t *data, struct process* process) {
if (phdr[i].p_memsz > phdr[i].p_filesz) {
memset((uint8_t*)phdr[i].p_vaddr + phdr[i].p_memsz, 0, phdr[i].p_memsz - phdr[i].p_filesz);
}
+ if (phdr[i].p_vaddr + phdr[i].p_memsz > dataseg) {
+ dataseg = phdr[i].p_vaddr + phdr[i].p_memsz;
+ dataseg = (dataseg & 0xFFFFF000) + 0x1000;
+ }
}
}
+ process->data = dataseg;
+
pagedir_switch(r);
sti();
diff --git a/src/kernel/mem/_dlmalloc.c b/src/kernel/mem/_dlmalloc.c
index 18dabab..30c6622 100644
--- a/src/kernel/mem/_dlmalloc.c
+++ b/src/kernel/mem/_dlmalloc.c
@@ -912,6 +912,14 @@ static FORCEINLINE int win32munmap(void* ptr, size_t size) {
/* #define TRY_LOCK(lk) ... */
/* static MLOCK_T malloc_global_mutex = ... */
+#define MLOCK_T uint32_t
+#define INITIAL_LOCK(l) (*l = MUTEX_UNLOCKED)
+#define DESTROY_LOCK(l) (0)
+#define ACQUIRE_LOCK(l) (mutex_lock (l))
+#define RELEASE_LOCK(l) (mutex_unlock (l))
+#define TRY_LOCK(l) (mutex_lockE(l))
+static MLOCK_T malloc_global_mutex = MUTEX_UNLOCKED;
+
#elif USE_SPIN_LOCKS
/* First, define CAS_LOCK and CLEAR_LOCK on ints */
diff --git a/src/kernel/mem/_dlmalloc.h b/src/kernel/mem/_dlmalloc.h
index a030da2..7b2e2cc 100644
--- a/src/kernel/mem/_dlmalloc.h
+++ b/src/kernel/mem/_dlmalloc.h
@@ -2,14 +2,19 @@
#define DEF_DLMALLOC_H
#include "lib/std.h"
+#include <stdlib_common.h>
+#include <string.h>
#define NO_MALLOC_STATS 1
#define LACKS_TIME_H
#define LACKS_UNISTD_H
#define LACKS_SYS_PARAM_H
+#define LACKS_STDLIB_H
#define USE_DL_PREFIX
+#define USE_LOCKS 2
+
/* Version identifier to allow people to support multiple versions */
#ifndef DLMALLOC_VERSION
diff --git a/src/kernel/mem/gdt.c b/src/kernel/mem/gdt.c
index 8ee403a..494aaf2 100644
--- a/src/kernel/mem/gdt.c
+++ b/src/kernel/mem/gdt.c
@@ -1,5 +1,5 @@
#include "gdt.h"
-#include <stdlib.h>
+#include <stdlib_common.h>
#include <core/monitor.h>
extern void gdt_flush(uint32_t); //ASM (imported from idt_.asm)
diff --git a/src/kernel/mem/mem.h b/src/kernel/mem/mem.h
index b6e9622..cb9c396 100644
--- a/src/kernel/mem/mem.h
+++ b/src/kernel/mem/mem.h
@@ -5,6 +5,7 @@
kmalloc_page and kfree_page are used mostly for paging. */
#include <types.h>
+#include "_dlmalloc.h"
void* kmalloc_page(size_t *phys);
void kfree_page(void* page);
diff --git a/src/kernel/mem/paging.c b/src/kernel/mem/paging.c
index 5953fc6..0527f06 100644
--- a/src/kernel/mem/paging.c
+++ b/src/kernel/mem/paging.c
@@ -1,6 +1,6 @@
#include "paging.h"
#include <bitset.h>
-#include <stdlib.h>
+#include <stdlib_common.h>
#include <core/monitor.h>
#include "mem.h"
#include "seg.h"
@@ -17,7 +17,7 @@ struct page_directory *kernel_pagedir, *current_pagedir;
uint32_t frame_alloc() {
uint32_t free = bitset_firstFree(&frames);
if (free == (uint32_t) -1) {
- PANIC("Out of memory!");
+ PANIC("No more frames to allocate, system is out of memory!");
}
bitset_set(&frames, free);
return free;
@@ -166,7 +166,6 @@ struct page *pagedir_getPage(struct page_directory *pd, uint32_t address, int ma
pd->tablesPhysical[table_idx] |= 0x07;
if (table_idx >= FIRST_KERNEL_PAGETABLE) {
- monitor_write("UKPI ");
tasking_updateKernelPagetable(table_idx, pd->tables[table_idx], pd->tablesPhysical[table_idx]);
}
diff --git a/src/kernel/task/idt.c b/src/kernel/task/idt.c
index ff129be..aed5ea8 100644
--- a/src/kernel/task/idt.c
+++ b/src/kernel/task/idt.c
@@ -6,7 +6,7 @@
#include "task.h"
#include "syscall.h"
-#include <stdlib.h>
+#include <stdlib_common.h>
extern void isr0();
extern void isr1();
@@ -102,7 +102,7 @@ void idt_irqHandler(struct registers regs) {
if (irq_handlers[regs.err_code] != 0) {
irq_handlers[regs.err_code](&regs);
}
- if (doSwitch) tasking_switch();
+ if (doSwitch) schedule();
}
/* Called in idt_.asm on a system call (interrupt 64).
@@ -208,7 +208,7 @@ void idt_handleIrq(int number, int_callback func) {
/* Tells the IRQ handler to wake up the current thread when specified IRQ fires. */
void idt_waitIrq(int number) {
- if (number < 16 && number >= 0 && proc_priv() <= PL_DRIVER) {
+ if (number < 16 && number >= 0 && proc_priv() <= PL_KERNEL) {
struct irq_waiter *tmp = kmalloc(sizeof(struct irq_waiter));
tmp->thread = current_thread;
tmp->next = irq_wakeup[number];
diff --git a/src/kernel/task/sched.c b/src/kernel/task/sched.c
index 2b0ef8a..aa41d5b 100644
--- a/src/kernel/task/sched.c
+++ b/src/kernel/task/sched.c
@@ -3,7 +3,7 @@
#include <mem/mem.h>
// Lower priority numbers have high priority. Priorities must start at 0.
-#define PRIORITIES 4 // we have 4 priority levels
+#define PRIORITIES 3 // we have 4 priority levels
#define PRIORITY(t) (t->process->privilege) //get priority for a thread
extern struct thread *idle_thread;
diff --git a/src/kernel/task/syscall.c b/src/kernel/task/syscall.c
index 5d40596..bd27eba 100644
--- a/src/kernel/task/syscall.c
+++ b/src/kernel/task/syscall.c
@@ -16,13 +16,14 @@
#define CALL4V(name, scname) static void scname(struct registers* r) { name(r->ebx, r->ecx, r->edx, r->esi); }
CALL0V(thread_exit, thread_exit_sc);
-CALL0V(tasking_switch, schedule_sc);
+CALL0V(schedule, schedule_sc);
CALL1V(thread_sleep, thread_sleep_sc);
CALL1V(process_exit, process_exit_sc);
CALL1(monitor_write, printk_sc);
CALL1V(idt_waitIrq, irq_wait_sc);
CALL0(proc_priv, proc_priv_sc);
-CALL2(process_setheapseg, proc_setheap_sc);
+CALL1(process_sbrk, proc_sbrk_sc);
+CALL1V(process_brk, proc_brk_sc);
static void thread_new_sc(struct registers* r) {
cli();
@@ -39,5 +40,6 @@ int_callback syscalls[NUMBER_OF_SYSCALLS] = {
thread_new_sc, //5
irq_wait_sc,
proc_priv_sc,
- proc_setheap_sc,
+ proc_sbrk_sc,
+ proc_brk_sc,
0 };
diff --git a/src/kernel/task/task.c b/src/kernel/task/task.c
index 7071248..9d98165 100644
--- a/src/kernel/task/task.c
+++ b/src/kernel/task/task.c
@@ -55,7 +55,7 @@ void tasking_updateKernelPagetable(uint32_t idx, struct page_table *table, uint3
}
/* Called when a timer IRQ fires. Does a context switch. */
-void tasking_switch() {
+void schedule() {
if (processes == 0) PANIC("No processes are running !");
asm volatile("cli");
@@ -122,7 +122,7 @@ uint32_t tasking_handleException(struct registers *regs) {
/* Puts the current thread in an inactive state. */
void thread_goInactive() {
current_thread->state = TS_WAKEWAIT;
- tasking_switch();
+ schedule();
}
/* Wakes up the given thread. */
@@ -157,7 +157,7 @@ void thread_exit2(uint32_t reason) { //See EX_TH_* defines in task.h
}
retrn:
sti();
- tasking_switch();
+ schedule();
}
/* For internal use only. Called by thread_exit and process_exit.
@@ -183,7 +183,7 @@ void thread_exit() {
}
/* System call. Exit the current process. */
-void process_exit(uint32_t retval) {
+void process_exit(size_t retval) {
if (retval == EX_TH_NORMAL || retval == EX_TH_EXCEPTION) retval = EX_PR_EXCEPTION;
thread_exit_stackJmp(retval);
}
@@ -193,7 +193,7 @@ void process_exit(uint32_t retval) {
It switches to user mode if necessary and calls the entry point. */
static void thread_run(void* u_esp, struct thread *thread, thread_entry entry_point, void *data) {
pagedir_switch(thread->process->pagedir);
- if (thread->process->privilege >= PL_SERVICE) { //User mode !
+ if (thread->process->privilege >= PL_USER) { //User mode !
uint32_t *stack = u_esp;
stack--; *stack = (uint32_t)data;
@@ -283,11 +283,12 @@ struct process *process_new(struct process* parent, uint32_t uid, uint32_t privi
p->parent = parent;
p->pagedir = pagedir_new();
p->next = processes;
- p->heapseg = 0;
+ p->data = 0;
+ p->dataseg = 0;
p->stack = 0;
- if (p->privilege >= PL_SERVICE) { //We are running in user mode
- size_t stacksBottom = 0xDF000000;
+ if (p->privilege >= PL_USER) { //We are running in user mode
+ size_t stacksBottom = K_HIGHHALF_ADDR - 0x01000000;
seg_map(simpleseg_make(stacksBottom, USER_STACK_SIZE, 1), p->pagedir, 0);
p->stack = stacksBottom + USER_STACK_SIZE - 4;
}
@@ -340,7 +341,7 @@ static void process_delete(struct process *pr) {
}
/* System call. Called by the app to define the place for the heap. */
-int process_setheapseg(size_t start, size_t end) { //syscall
+/*int process_setheapseg(size_t start, size_t end) { //syscall
struct process *p = current_thread->process;
if (start >= K_HIGHHALF_ADDR || end >= K_HIGHHALF_ADDR) return -1;
if (p->heapseg == 0) {
@@ -359,4 +360,51 @@ int process_setheapseg(size_t start, size_t end) { //syscall
} else {
return simpleseg_resize(p->heapseg, end - start);
}
+}*/
+
+size_t process_sbrk(size_t size) {
+ struct process *p = current_thread->process;
+ if (p->data == 0) return -1;
+ ASSERT(p->data < K_HIGHHALF_ADDR);
+ if (p->data + size >= K_HIGHHALF_ADDR) return -1;
+
+ size_t ret;
+ if (p->dataseg == 0) {
+ size_t start = p->data;
+ if (start & 0x0FFF) start = (start & 0xFFFFF000) + 0x1000;
+ size_t end = start + size;
+ if (end & 0x0FFF) end = (end & 0xFFFFF000) + 0x1000;
+
+ struct segment *s = simpleseg_make(start, end - start, 1);
+ if (s == 0) return -5;
+ p->dataseg = seg_map(s, p->pagedir, 0);
+ if (p->dataseg == 0) return -1;
+
+ ret = start;
+ p->data = start + size;
+ } else {
+ size_t start = p->dataseg->start;
+ size_t end = p->data + size;
+ if (end <= start) return -1;
+
+ if (end & 0x0FFF) end = (end & 0xFFFFF000) + 0x1000;
+ simpleseg_resize(p->dataseg, end - start);
+
+ ret = p->data;
+ p->data += size;
+ }
+ /* (DBG) monitor_write("(sbrk ");
+ monitor_writeHex(size);
+ monitor_write(" ");
+ monitor_writeHex(ret);
+ monitor_write(")"); */
+ return ret;
}
+
+void process_brk(size_t ptr) {
+ struct process *p = current_thread->process;
+
+ ASSERT(ptr < K_HIGHHALF_ADDR);
+ process_sbrk(ptr - p->data);
+}
+
diff --git a/src/kernel/task/task.h b/src/kernel/task/task.h
index fdffa11..63cb35a 100644
--- a/src/kernel/task/task.h
+++ b/src/kernel/task/task.h
@@ -8,17 +8,15 @@
#define TS_RUNNING 0
#define TS_WAKEWAIT 2 //Waiting to be waked up by something precise (thread currently blocked)
-#define PL_UNKNOWN 4
-#define PL_USER 3
-#define PL_SERVICE 2
-#define PL_DRIVER 1
+#define PL_UNKNOWN 2
+#define PL_USER 1
#define PL_KERNEL 0
#define EX_TH_NORMAL 0x10000 //ERROR code : just one thread exits, because it has to
#define EX_TH_EXCEPTION 0x10001 //ERROR code : just one thread exits, because of an unhandled exception
#define EX_PR_EXCEPTION 0x10002 //ERROR code : all process finishes, because of an unhandled exception
-#define USER_STACK_SIZE 0x8000 //32k, but pages will be mapped one by one as used
+#define USER_STACK_SIZE 0x10000 //64k, but pages will be mapped one by one as they are used
typedef void (*thread_entry)(void*);
@@ -26,9 +24,9 @@ struct process {
uint32_t pid, uid, privilege, thread_count;
struct process *parent;
struct page_directory *pagedir;
- size_t stack;
+ size_t stack, data;
- struct segment_map *heapseg;
+ struct segment_map *dataseg;
struct process *next; //Forms a linked list
struct thread *threads;
@@ -48,7 +46,7 @@ struct thread {
extern struct thread *current_thread;
void tasking_init();
-void tasking_switch();
+void schedule();
void tasking_updateKernelPagetable(uint32_t idx, struct page_table *table, uint32_t tablePhysical);
uint32_t tasking_handleException(struct registers *regs);
@@ -59,7 +57,8 @@ struct thread * thread_new(struct process *proc, thread_entry entry_point, void
struct process* process_new(struct process *parent, uint32_t uid, uint32_t privilege);
void thread_exit(); //syscall
-void process_exit(uint32_t retval); //syscall
-int process_setheapseg(size_t start, size_t end); //syscall
+void process_exit(size_t retval); //syscall
+size_t process_sbrk(size_t size);
+void process_brk(size_t ptr);
#endif