From e9683297bf480f9590b0e5796f4520fb430e2e03 Mon Sep 17 00:00:00 2001 From: Alex AUVOLAT Date: Tue, 1 May 2012 17:42:36 +0200 Subject: Now using Doug Lea's malloc for userland too. And improved stability. --- src/kernel/task/idt.c | 6 ++--- src/kernel/task/sched.c | 2 +- src/kernel/task/syscall.c | 8 +++--- src/kernel/task/task.c | 66 ++++++++++++++++++++++++++++++++++++++++------- src/kernel/task/task.h | 19 +++++++------- 5 files changed, 75 insertions(+), 26 deletions(-) (limited to 'src/kernel/task') 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 +#include 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](®s); } - 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 // 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 -- cgit v1.2.3