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_ */