kern
changeset 56:0be4615594df
finally, runqueues, blocking, waking up, idle loop etc, all seem to work fine
on a single user process... Next up: try forking another one :)
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Mon, 15 Aug 2011 06:17:58 +0300 |
parents | 88a6c4e192f9 |
children | 437360696883 |
files | src/klibc/assert.h src/proc.c src/proc.h src/sched.c src/syscall.c src/test_proc.S src/timer.c src/timer.h |
diffstat | 8 files changed, 69 insertions(+), 38 deletions(-) [+] |
line diff
1.1 --- a/src/klibc/assert.h Mon Aug 15 04:03:39 2011 +0300 1.2 +++ b/src/klibc/assert.h Mon Aug 15 06:17:58 2011 +0300 1.3 @@ -5,7 +5,7 @@ 1.4 1.5 #define assert(x) \ 1.6 if(!(x)) { \ 1.7 - panic("Kernel assertion failed: " #x "\n"); \ 1.8 + panic("Kernel assertion failed at " __FILE__ ":%d: " #x "\n", __LINE__); \ 1.9 } 1.10 1.11 #endif /* ASSERT_H_ */
2.1 --- a/src/proc.c Mon Aug 15 04:03:39 2011 +0300 2.2 +++ b/src/proc.c Mon Aug 15 06:17:58 2011 +0300 2.3 @@ -24,7 +24,13 @@ 2.4 void test_proc_end(void); 2.5 2.6 static struct process proc[MAX_PROC]; 2.7 -static int cur_pid; 2.8 + 2.9 +/* cur_pid: pid of the currently executing process. 2.10 + * when we're in the idle process cur_pid will be 0. 2.11 + * last_pid: pid of the last real process that was running, this should 2.12 + * never become 0. Essentially this defines the active kernel stack. 2.13 + */ 2.14 +static int cur_pid, last_pid; 2.15 2.16 static struct task_state *tss; 2.17 2.18 @@ -121,7 +127,8 @@ 2.19 /* add it to the scheduler queues */ 2.20 add_proc(p->id); 2.21 2.22 - cur_pid = p->id; /* make it current */ 2.23 + /* make it current */ 2.24 + set_current_pid(p->id); 2.25 2.26 /* execute a fake return from interrupt with the fake stack frame */ 2.27 intr_ret(ifrm); 2.28 @@ -130,31 +137,43 @@ 2.29 2.30 void context_switch(int pid) 2.31 { 2.32 - struct process *prev, *new; 2.33 + static struct process *prev, *new; 2.34 2.35 assert(get_intr_state() == 0); 2.36 + assert(pid > 0); 2.37 + assert(last_pid > 0); 2.38 2.39 - if(cur_pid == pid) { 2.40 - return; /* nothing to be done */ 2.41 - } 2.42 - prev = proc + cur_pid; 2.43 + prev = proc + last_pid; 2.44 new = proc + pid; 2.45 2.46 - /* push all registers onto the stack before switching stacks */ 2.47 - push_regs(); 2.48 + if(last_pid != pid) { 2.49 + /* push all registers onto the stack before switching stacks */ 2.50 + push_regs(); 2.51 2.52 - prev->ctx.stack_ptr = switch_stack(new->ctx.stack_ptr); 2.53 + prev->ctx.stack_ptr = switch_stack(new->ctx.stack_ptr); 2.54 2.55 - /* restore registers from the new stack */ 2.56 - pop_regs(); 2.57 + /* restore registers from the new stack */ 2.58 + pop_regs(); 2.59 2.60 - /* switch to the new process' address space */ 2.61 - set_pgdir_addr(new->ctx.pgtbl_paddr); 2.62 + /* switch to the new process' address space */ 2.63 + set_pgdir_addr(new->ctx.pgtbl_paddr); 2.64 2.65 - /* make sure we'll return to the correct kernel stack next time 2.66 - * we enter from userspace 2.67 - */ 2.68 - tss->esp0 = PAGE_TO_ADDR(new->kern_stack_pg) + KERN_STACK_SIZE; 2.69 + /* make sure we'll return to the correct kernel stack next time 2.70 + * we enter from userspace 2.71 + */ 2.72 + tss->esp0 = PAGE_TO_ADDR(new->kern_stack_pg) + KERN_STACK_SIZE; 2.73 + } 2.74 + 2.75 + set_current_pid(new->id); 2.76 +} 2.77 + 2.78 + 2.79 +void set_current_pid(int pid) 2.80 +{ 2.81 + cur_pid = pid; 2.82 + if(pid > 0) { 2.83 + last_pid = pid; 2.84 + } 2.85 } 2.86 2.87 int get_current_pid(void) 2.88 @@ -164,7 +183,7 @@ 2.89 2.90 struct process *get_current_proc(void) 2.91 { 2.92 - return cur_pid ? &proc[cur_pid] : 0; 2.93 + return cur_pid > 0 ? &proc[cur_pid] : 0; 2.94 } 2.95 2.96 struct process *get_process(int pid)
3.1 --- a/src/proc.h Mon Aug 15 04:03:39 2011 +0300 3.2 +++ b/src/proc.h Mon Aug 15 06:17:58 2011 +0300 3.3 @@ -47,6 +47,7 @@ 3.4 3.5 void context_switch(int pid); 3.6 3.7 +void set_current_pid(int pid); 3.8 int get_current_pid(void); 3.9 struct process *get_current_proc(void); 3.10 struct process *get_process(int pid);
4.1 --- a/src/sched.c Mon Aug 15 04:03:39 2011 +0300 4.2 +++ b/src/sched.c Mon Aug 15 06:17:58 2011 +0300 4.3 @@ -30,8 +30,15 @@ 4.4 disable_intr(); 4.5 4.6 if(EMPTY(&runq)) { 4.7 + if(!get_current_proc()) { 4.8 + /* we're already in the idle process, don't reenter it 4.9 + * or you'll fill up the stack very quickly. 4.10 + */ 4.11 + return; 4.12 + } 4.13 + 4.14 idle_proc(); 4.15 - /* this won't return, it'll just wake up in an interrupt later */ 4.16 + return; 4.17 } 4.18 4.19 /* if the current process exhausted its timeslice, 4.20 @@ -88,6 +95,9 @@ 4.21 4.22 p->state = STATE_BLOCKED; 4.23 p->wait_addr = wait_addr; 4.24 + 4.25 + /* call the scheduler to give time to another process */ 4.26 + schedule(); 4.27 } 4.28 4.29 /* wake up all the processes sleeping on this address */ 4.30 @@ -124,9 +134,14 @@ 4.31 struct intr_frame *ifrm = get_intr_frame(); 4.32 end_of_irq(INTR_TO_IRQ(ifrm->inum)); 4.33 4.34 + set_current_pid(0); 4.35 + 4.36 /* make sure interrupts are enabled before halting */ 4.37 - enable_intr(); 4.38 - halt_cpu(); 4.39 + while(EMPTY(&runq)) { 4.40 + enable_intr(); 4.41 + halt_cpu(); 4.42 + disable_intr(); 4.43 + } 4.44 } 4.45 4.46
5.1 --- a/src/syscall.c Mon Aug 15 04:03:39 2011 +0300 5.2 +++ b/src/syscall.c Mon Aug 15 06:17:58 2011 +0300 5.3 @@ -55,6 +55,9 @@ 5.4 5.5 static int sys_sleep(int sec) 5.6 { 5.7 - printf("SYSCALL: sleep\n"); 5.8 - return -1; 5.9 + printf("process %d will sleep for %d seconds\n", get_current_pid(), sec); 5.10 + 5.11 + sleep(sec * 1000); 5.12 + 5.13 + return 0; 5.14 }
6.1 --- a/src/test_proc.S Mon Aug 15 04:03:39 2011 +0300 6.2 +++ b/src/test_proc.S Mon Aug 15 06:17:58 2011 +0300 6.3 @@ -10,7 +10,7 @@ 6.4 6.5 /* --- sleep for 5 seconds --- */ 6.6 movl $SYS_SLEEP, %eax 6.7 - movl $5, %ebx 6.8 + movl $3, %ebx 6.9 int $SYSCALL_INT 6.10 6.11 jmp test_proc
7.1 --- a/src/timer.c Mon Aug 15 04:03:39 2011 +0300 7.2 +++ b/src/timer.c Mon Aug 15 06:17:58 2011 +0300 7.3 @@ -136,11 +136,10 @@ 7.4 static void intr_handler(int inum) 7.5 { 7.6 int istate; 7.7 - struct process *cur_proc; 7.8 7.9 nticks++; 7.10 7.11 - printf("TICKS: %d\n", nticks); 7.12 + /*printf("TICKS: %d\n", nticks);*/ 7.13 7.14 istate = get_intr_state(); 7.15 disable_intr(); 7.16 @@ -149,7 +148,7 @@ 7.17 if(evlist) { 7.18 evlist->dt--; 7.19 7.20 - while(evlist->dt <= 0) { 7.21 + while(evlist && evlist->dt <= 0) { 7.22 struct timer_event *ev = evlist; 7.23 evlist = evlist->next; 7.24 7.25 @@ -160,12 +159,8 @@ 7.26 } 7.27 } 7.28 7.29 - if((cur_proc = get_current_proc())) { 7.30 - /* if the timeslice of this process has expire, call the scheduler */ 7.31 - if(--cur_proc->ticks_left <= 0) { 7.32 - schedule(); 7.33 - } 7.34 - } 7.35 + /* call the scheduler to decide if it's time to switch processes */ 7.36 + schedule(); 7.37 7.38 set_intr_state(istate); 7.39 }
8.1 --- a/src/timer.h Mon Aug 15 04:03:39 2011 +0300 8.2 +++ b/src/timer.h Mon Aug 15 06:17:58 2011 +0300 8.3 @@ -1,12 +1,10 @@ 8.4 #ifndef _TIMER_H_ 8.5 #define _TIMER_H_ 8.6 8.7 -typedef void (*timer_func_t)(void*); 8.8 - 8.9 unsigned long nticks; 8.10 8.11 void init_timer(void); 8.12 8.13 -int start_timer(unsigned long msec, timer_func_t cbfunc, void *cbarg); 8.14 +void sleep(unsigned long msec); 8.15 8.16 #endif /* _TIMER_H_ */