# HG changeset patch # User John Tsiombikas # Date 1313378278 -10800 # Node ID 0be4615594df271f76be24c33321877284a95846 # Parent 88a6c4e192f916e5bcc582e7e4cd47651f26c118 finally, runqueues, blocking, waking up, idle loop etc, all seem to work fine on a single user process... Next up: try forking another one :) diff -r 88a6c4e192f9 -r 0be4615594df src/klibc/assert.h --- a/src/klibc/assert.h Mon Aug 15 04:03:39 2011 +0300 +++ b/src/klibc/assert.h Mon Aug 15 06:17:58 2011 +0300 @@ -5,7 +5,7 @@ #define assert(x) \ if(!(x)) { \ - panic("Kernel assertion failed: " #x "\n"); \ + panic("Kernel assertion failed at " __FILE__ ":%d: " #x "\n", __LINE__); \ } #endif /* ASSERT_H_ */ diff -r 88a6c4e192f9 -r 0be4615594df src/proc.c --- a/src/proc.c Mon Aug 15 04:03:39 2011 +0300 +++ b/src/proc.c Mon Aug 15 06:17:58 2011 +0300 @@ -24,7 +24,13 @@ void test_proc_end(void); static struct process proc[MAX_PROC]; -static int cur_pid; + +/* cur_pid: pid of the currently executing process. + * when we're in the idle process cur_pid will be 0. + * last_pid: pid of the last real process that was running, this should + * never become 0. Essentially this defines the active kernel stack. + */ +static int cur_pid, last_pid; static struct task_state *tss; @@ -121,7 +127,8 @@ /* add it to the scheduler queues */ add_proc(p->id); - cur_pid = p->id; /* make it current */ + /* make it current */ + set_current_pid(p->id); /* execute a fake return from interrupt with the fake stack frame */ intr_ret(ifrm); @@ -130,31 +137,43 @@ void context_switch(int pid) { - struct process *prev, *new; + static struct process *prev, *new; assert(get_intr_state() == 0); + assert(pid > 0); + assert(last_pid > 0); - if(cur_pid == pid) { - return; /* nothing to be done */ - } - prev = proc + cur_pid; + prev = proc + last_pid; new = proc + pid; - /* push all registers onto the stack before switching stacks */ - push_regs(); + if(last_pid != pid) { + /* push all registers onto the stack before switching stacks */ + push_regs(); - prev->ctx.stack_ptr = switch_stack(new->ctx.stack_ptr); + prev->ctx.stack_ptr = switch_stack(new->ctx.stack_ptr); - /* restore registers from the new stack */ - pop_regs(); + /* restore registers from the new stack */ + pop_regs(); - /* switch to the new process' address space */ - set_pgdir_addr(new->ctx.pgtbl_paddr); + /* switch to the new process' address space */ + set_pgdir_addr(new->ctx.pgtbl_paddr); - /* make sure we'll return to the correct kernel stack next time - * we enter from userspace - */ - tss->esp0 = PAGE_TO_ADDR(new->kern_stack_pg) + KERN_STACK_SIZE; + /* make sure we'll return to the correct kernel stack next time + * we enter from userspace + */ + tss->esp0 = PAGE_TO_ADDR(new->kern_stack_pg) + KERN_STACK_SIZE; + } + + set_current_pid(new->id); +} + + +void set_current_pid(int pid) +{ + cur_pid = pid; + if(pid > 0) { + last_pid = pid; + } } int get_current_pid(void) @@ -164,7 +183,7 @@ struct process *get_current_proc(void) { - return cur_pid ? &proc[cur_pid] : 0; + return cur_pid > 0 ? &proc[cur_pid] : 0; } struct process *get_process(int pid) diff -r 88a6c4e192f9 -r 0be4615594df src/proc.h --- a/src/proc.h Mon Aug 15 04:03:39 2011 +0300 +++ b/src/proc.h Mon Aug 15 06:17:58 2011 +0300 @@ -47,6 +47,7 @@ void context_switch(int pid); +void set_current_pid(int pid); int get_current_pid(void); struct process *get_current_proc(void); struct process *get_process(int pid); diff -r 88a6c4e192f9 -r 0be4615594df src/sched.c --- a/src/sched.c Mon Aug 15 04:03:39 2011 +0300 +++ b/src/sched.c Mon Aug 15 06:17:58 2011 +0300 @@ -30,8 +30,15 @@ disable_intr(); if(EMPTY(&runq)) { + if(!get_current_proc()) { + /* we're already in the idle process, don't reenter it + * or you'll fill up the stack very quickly. + */ + return; + } + idle_proc(); - /* this won't return, it'll just wake up in an interrupt later */ + return; } /* if the current process exhausted its timeslice, @@ -88,6 +95,9 @@ p->state = STATE_BLOCKED; p->wait_addr = wait_addr; + + /* call the scheduler to give time to another process */ + schedule(); } /* wake up all the processes sleeping on this address */ @@ -124,9 +134,14 @@ struct intr_frame *ifrm = get_intr_frame(); end_of_irq(INTR_TO_IRQ(ifrm->inum)); + set_current_pid(0); + /* make sure interrupts are enabled before halting */ - enable_intr(); - halt_cpu(); + while(EMPTY(&runq)) { + enable_intr(); + halt_cpu(); + disable_intr(); + } } diff -r 88a6c4e192f9 -r 0be4615594df src/syscall.c --- a/src/syscall.c Mon Aug 15 04:03:39 2011 +0300 +++ b/src/syscall.c Mon Aug 15 06:17:58 2011 +0300 @@ -55,6 +55,9 @@ static int sys_sleep(int sec) { - printf("SYSCALL: sleep\n"); - return -1; + printf("process %d will sleep for %d seconds\n", get_current_pid(), sec); + + sleep(sec * 1000); + + return 0; } diff -r 88a6c4e192f9 -r 0be4615594df src/test_proc.S --- a/src/test_proc.S Mon Aug 15 04:03:39 2011 +0300 +++ b/src/test_proc.S Mon Aug 15 06:17:58 2011 +0300 @@ -10,7 +10,7 @@ /* --- sleep for 5 seconds --- */ movl $SYS_SLEEP, %eax - movl $5, %ebx + movl $3, %ebx int $SYSCALL_INT jmp test_proc diff -r 88a6c4e192f9 -r 0be4615594df src/timer.c --- a/src/timer.c Mon Aug 15 04:03:39 2011 +0300 +++ b/src/timer.c Mon Aug 15 06:17:58 2011 +0300 @@ -136,11 +136,10 @@ static void intr_handler(int inum) { int istate; - struct process *cur_proc; nticks++; - printf("TICKS: %d\n", nticks); + /*printf("TICKS: %d\n", nticks);*/ istate = get_intr_state(); disable_intr(); @@ -149,7 +148,7 @@ if(evlist) { evlist->dt--; - while(evlist->dt <= 0) { + while(evlist && evlist->dt <= 0) { struct timer_event *ev = evlist; evlist = evlist->next; @@ -160,12 +159,8 @@ } } - if((cur_proc = get_current_proc())) { - /* if the timeslice of this process has expire, call the scheduler */ - if(--cur_proc->ticks_left <= 0) { - schedule(); - } - } + /* call the scheduler to decide if it's time to switch processes */ + schedule(); set_intr_state(istate); } diff -r 88a6c4e192f9 -r 0be4615594df src/timer.h --- a/src/timer.h Mon Aug 15 04:03:39 2011 +0300 +++ b/src/timer.h Mon Aug 15 06:17:58 2011 +0300 @@ -1,12 +1,10 @@ #ifndef _TIMER_H_ #define _TIMER_H_ -typedef void (*timer_func_t)(void*); - unsigned long nticks; void init_timer(void); -int start_timer(unsigned long msec, timer_func_t cbfunc, void *cbarg); +void sleep(unsigned long msec); #endif /* _TIMER_H_ */