kern

changeset 51:b1e8c8251884

lalalala
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 01 Aug 2011 06:45:29 +0300
parents 1d8877d12de0
children fa65b4f45366
files run src/config.h src/intr.c src/intr.h src/proc.c src/proc.h src/sched.c src/sched.h src/syscall.c src/syscall.h src/sysnum.h src/test_proc.S src/timer.c src/timer.h src/vm.c
diffstat 15 files changed, 418 insertions(+), 41 deletions(-) [+]
line diff
     1.1 --- a/run	Sat Jul 30 07:35:53 2011 +0300
     1.2 +++ b/run	Mon Aug 01 06:45:29 2011 +0300
     1.3 @@ -1,3 +1,3 @@
     1.4  #!/bin/sh
     1.5  
     1.6 -qemu -kernel kernel.elf -soundhw pcspk
     1.7 +qemu -kernel kernel.elf -soundhw pcspk $*
     2.1 --- a/src/config.h	Sat Jul 30 07:35:53 2011 +0300
     2.2 +++ b/src/config.h	Mon Aug 01 06:45:29 2011 +0300
     2.3 @@ -4,4 +4,7 @@
     2.4  /* frequency of generated timer ticks in hertz */
     2.5  #define TICK_FREQ_HZ		250
     2.6  
     2.7 +#define TIMESLICE			100
     2.8 +#define TIMESLICE_TICKS		(TIMESLICE * TICK_FREQ_HZ / 1000)
     2.9 +
    2.10  #endif	/* _CONFIG_H_ */
     3.1 --- a/src/intr.c	Sat Jul 30 07:35:53 2011 +0300
     3.2 +++ b/src/intr.c	Mon Aug 01 06:45:29 2011 +0300
     3.3 @@ -38,7 +38,6 @@
     3.4  static void init_pic(int offset);
     3.5  static void gate_desc(desc_t *desc, uint16_t sel, uint32_t addr, int dpl, int type);
     3.6  static void set_intr_entry(int num, void (*handler)(void));
     3.7 -static void end_of_irq(int irq);
     3.8  
     3.9  /* defined in intr-asm.S */
    3.10  void set_idt(uint32_t addr, uint16_t limit);
    3.11 @@ -88,7 +87,7 @@
    3.12  void dispatch_intr(struct intr_frame frm)
    3.13  {
    3.14  	if(intr_func[frm.inum]) {
    3.15 -		intr_func[frm.inum](frm.inum, frm.err);
    3.16 +		intr_func[frm.inum](frm.inum, &frm);
    3.17  	} else {
    3.18  		if(frm.inum < 32) {
    3.19  			panic("unhandled exception %d, error code: %d\n", frm.inum, frm.err);
    3.20 @@ -141,7 +140,7 @@
    3.21  	gate_desc(idt + num, selector(SEGM_KCODE, 0), (uint32_t)handler, 0, type);
    3.22  }
    3.23  
    3.24 -static void end_of_irq(int irq)
    3.25 +void end_of_irq(int irq)
    3.26  {
    3.27  	if(irq > 7) {
    3.28  		outb(OCW2_EOI, PIC2_CMD);
     4.1 --- a/src/intr.h	Sat Jul 30 07:35:53 2011 +0300
     4.2 +++ b/src/intr.h	Mon Aug 01 06:45:29 2011 +0300
     4.3 @@ -28,7 +28,7 @@
     4.4  
     4.5  
     4.6  
     4.7 -typedef void (*intr_func_t)(int, uint32_t);
     4.8 +typedef void (*intr_func_t)(int, struct intr_frame *frm);
     4.9  
    4.10  
    4.11  void init_intr(void);
    4.12 @@ -41,4 +41,6 @@
    4.13  
    4.14  void intr_ret(struct intr_frame ifrm);
    4.15  
    4.16 +void end_of_irq(int irq);
    4.17 +
    4.18  #endif	/* INTR_H_ */
     5.1 --- a/src/proc.c	Sat Jul 30 07:35:53 2011 +0300
     5.2 +++ b/src/proc.c	Mon Aug 01 06:45:29 2011 +0300
     5.3 @@ -5,6 +5,8 @@
     5.4  #include "segm.h"
     5.5  #include "intr.h"
     5.6  #include "panic.h"
     5.7 +#include "syscall.h"
     5.8 +#include "sched.h"
     5.9  
    5.10  
    5.11  /* defined in test_proc.S */
    5.12 @@ -18,50 +20,50 @@
    5.13  {
    5.14  	int proc_size_pg, img_start_pg, stack_pg;
    5.15  	void *img_start;
    5.16 -	cur_pid = -1;
    5.17 +	cur_pid = 0;
    5.18 +
    5.19 +	init_syscall();
    5.20  
    5.21  	/* prepare the first process */
    5.22 +	proc[1].id = 1;
    5.23 +	proc[1].parent = 0;
    5.24  
    5.25  	/* allocate a chunk of memory for the process image
    5.26  	 * and copy the code of test_proc there.
    5.27  	 * (should be mapped at a fixed address)
    5.28  	 */
    5.29 -	/*proc_size_pg = (test_proc_end - test_proc) / PGSIZE + 1;
    5.30 +	proc_size_pg = (test_proc_end - test_proc) / PGSIZE + 1;
    5.31  	if((img_start_pg = pgalloc(proc_size_pg, MEM_USER)) == -1) {
    5.32  		panic("failed to allocate space for the init process image\n");
    5.33  	}
    5.34  	img_start = (void*)PAGE_TO_ADDR(img_start_pg);
    5.35 -	memcpy(img_start, test_proc, proc_size_pg * PGSIZE);*/
    5.36 -	img_start = test_proc;
    5.37 +	memcpy(img_start, test_proc, proc_size_pg * PGSIZE);
    5.38  
    5.39  	/* instruction pointer at the beginning of the process image */
    5.40 -	proc[0].ctx.instr_ptr = (uint32_t)img_start;
    5.41 +	proc[1].ctx.instr_ptr = (uint32_t)img_start;
    5.42  
    5.43  	/* allocate the first page of the process stack */
    5.44  	stack_pg = ADDR_TO_PAGE(KMEM_START) - 1;
    5.45  	if(pgalloc_vrange(stack_pg, 1) == -1) {
    5.46  		panic("failed to allocate user stack page\n");
    5.47  	}
    5.48 -	proc[0].ctx.stack_ptr = PAGE_TO_ADDR(stack_pg) + PGSIZE;
    5.49 +	proc[1].ctx.stack_ptr = PAGE_TO_ADDR(stack_pg) + PGSIZE;
    5.50  
    5.51  	/* create the virtual address space for this process */
    5.52 -	proc[0].ctx.pgtbl_paddr = clone_vm();
    5.53 +	proc[1].ctx.pgtbl_paddr = clone_vm();
    5.54  
    5.55  	/* we don't need the image and the stack in this address space */
    5.56 -	/*unmap_page_range(img_start_pg, proc_size_pg);
    5.57 -	pgfree(img_start_pg, proc_size_pg);*/
    5.58 +	unmap_page_range(img_start_pg, proc_size_pg);
    5.59 +	pgfree(img_start_pg, proc_size_pg);
    5.60  
    5.61  	unmap_page(stack_pg);
    5.62  	pgfree(stack_pg, 1);
    5.63  
    5.64 +	/* add it to the scheduler queues */
    5.65 +	//add_proc(1, STATE_RUNNING);
    5.66  
    5.67 -	/* switch to it by calling a function that takes the context
    5.68 -	 * of the current process, plugs the values into the interrupt
    5.69 -	 * stack, and calls iret.
    5.70 -	 * (should also set ss0/sp0 in TSS before returning)
    5.71 -	 */
    5.72 -	context_switch(0);
    5.73 -	/* XXX this will never return */
    5.74 +	/* switch to the initial process, this never returns */
    5.75 +	context_switch(1);
    5.76  }
    5.77  
    5.78  
    5.79 @@ -76,7 +78,7 @@
    5.80  	ifrm.inum = ifrm.err = 0;
    5.81  
    5.82  	ifrm.regs = ctx->regs;
    5.83 -	ifrm.eflags = ctx->flags;
    5.84 +	ifrm.eflags = ctx->flags | (1 << 9);
    5.85  
    5.86  	ifrm.eip = ctx->instr_ptr;
    5.87  	ifrm.cs = selector(SEGM_KCODE, 0);	/* XXX change this when we setup the TSS */
    5.88 @@ -89,3 +91,18 @@
    5.89  
    5.90  	intr_ret(ifrm);
    5.91  }
    5.92 +
    5.93 +int get_current_pid(void)
    5.94 +{
    5.95 +	return cur_pid;
    5.96 +}
    5.97 +
    5.98 +struct process *get_current_proc(void)
    5.99 +{
   5.100 +	return cur_pid ? &proc[cur_pid] : 0;
   5.101 +}
   5.102 +
   5.103 +struct process *get_process(int pid)
   5.104 +{
   5.105 +	return &proc[pid];
   5.106 +}
     6.1 --- a/src/proc.h	Sat Jul 30 07:35:53 2011 +0300
     6.2 +++ b/src/proc.h	Mon Aug 01 06:45:29 2011 +0300
     6.3 @@ -15,14 +15,29 @@
     6.4  	/* TODO add FPU state */
     6.5  };
     6.6  
     6.7 +enum proc_state {
     6.8 +	STATE_RUNNING,
     6.9 +	STATE_BLOCKED,
    6.10 +	STATE_ZOMBIE
    6.11 +};
    6.12 +
    6.13  
    6.14  struct process {
    6.15 -	int parent;
    6.16 +	int id, parent;
    6.17 +	enum proc_state state;
    6.18 +
    6.19 +	int ticks_left;
    6.20  	struct context ctx;
    6.21 +
    6.22 +	struct process *next, *prev;	/* for the scheduler queues */
    6.23  };
    6.24  
    6.25  void init_proc(void);
    6.26  
    6.27  void context_switch(int pid);
    6.28  
    6.29 +int get_current_pid(void);
    6.30 +struct process *get_current_proc(void);
    6.31 +struct process *get_process(int pid);
    6.32 +
    6.33  #endif	/* PROC_H_ */
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/src/sched.c	Mon Aug 01 06:45:29 2011 +0300
     7.3 @@ -0,0 +1,154 @@
     7.4 +#include <stdio.h>
     7.5 +#include "sched.h"
     7.6 +#include "proc.h"
     7.7 +#include "intr.h"
     7.8 +#include "asmops.h"
     7.9 +#include "config.h"
    7.10 +
    7.11 +#define EMPTY(q)	((q).head == 0)
    7.12 +
    7.13 +struct proc_list {
    7.14 +	struct process *head, *tail;
    7.15 +};
    7.16 +
    7.17 +static void ins_back(struct proc_list *q, struct process *proc);
    7.18 +static void ins_front(struct proc_list *q, struct process *proc);
    7.19 +static void remove(struct proc_list *q, struct process *proc);
    7.20 +
    7.21 +static struct proc_list runq;
    7.22 +static struct proc_list waitq;
    7.23 +static struct proc_list zombieq;
    7.24 +
    7.25 +void schedule(void)
    7.26 +{
    7.27 +	if(EMPTY(runq)) {
    7.28 +		/* idle "process".
    7.29 +		 * make sure interrupts are enabled before halting
    7.30 +		 */
    7.31 +		enable_intr();
    7.32 +		halt_cpu();
    7.33 +		/* this won't return, it'll just wake up in an interrupt later */
    7.34 +	}
    7.35 +
    7.36 +	disable_intr();
    7.37 +
    7.38 +	/* if the current process exhausted its timeslice,
    7.39 +	 * move it to the back of the queue.
    7.40 +	 */
    7.41 +	if(runq.head->ticks_left <= 0) {
    7.42 +		if(runq.head->next) {
    7.43 +			struct process *proc = runq.head;
    7.44 +			remove(&runq, proc);
    7.45 +			ins_back(&runq, proc);
    7.46 +		}
    7.47 +
    7.48 +		/* start a new timeslice */
    7.49 +		runq.head->ticks_left = TIMESLICE_TICKS;
    7.50 +	}
    7.51 +
    7.52 +	/* no need to re-enable interrupts, they will be enabled with the iret */
    7.53 +	context_switch(runq.head->id);
    7.54 +}
    7.55 +
    7.56 +int add_proc(int pid, enum proc_state state)
    7.57 +{
    7.58 +	int istate;
    7.59 +	struct proc_list *q;
    7.60 +	struct process *proc = get_process(pid);
    7.61 +
    7.62 +	istate = get_intr_state();
    7.63 +	disable_intr();
    7.64 +
    7.65 +	q = state == STATE_RUNNING ? &runq : &waitq;
    7.66 +
    7.67 +	ins_back(q, proc);
    7.68 +	proc->state = state;
    7.69 +
    7.70 +	set_intr_state(istate);
    7.71 +	return 0;
    7.72 +}
    7.73 +
    7.74 +int block_proc(int pid)
    7.75 +{
    7.76 +	int istate;
    7.77 +	struct process *proc = get_process(pid);
    7.78 +
    7.79 +	if(proc->state != STATE_RUNNING) {
    7.80 +		printf("block_proc: process %d not running\n", pid);
    7.81 +		return -1;
    7.82 +	}
    7.83 +
    7.84 +	istate = get_intr_state();
    7.85 +	disable_intr();
    7.86 +
    7.87 +	remove(&runq, proc);
    7.88 +	ins_back(&waitq, proc);
    7.89 +	proc->state = STATE_BLOCKED;
    7.90 +
    7.91 +	set_intr_state(istate);
    7.92 +	return 0;
    7.93 +}
    7.94 +
    7.95 +int unblock_proc(int pid)
    7.96 +{
    7.97 +	int istate;
    7.98 +	struct process *proc = get_process(pid);
    7.99 +
   7.100 +	if(proc->state != STATE_BLOCKED) {
   7.101 +		printf("unblock_proc: process %d not blocked\n", pid);
   7.102 +		return -1;
   7.103 +	}
   7.104 +
   7.105 +	istate = get_intr_state();
   7.106 +	disable_intr();
   7.107 +
   7.108 +	remove(&waitq, proc);
   7.109 +	ins_back(&runq, proc);
   7.110 +	proc->state = STATE_RUNNING;
   7.111 +
   7.112 +	set_intr_state(istate);
   7.113 +	return 0;
   7.114 +}
   7.115 +
   7.116 +
   7.117 +static void ins_back(struct proc_list *q, struct process *proc)
   7.118 +{
   7.119 +	if(EMPTY(*q)) {
   7.120 +		q->head = proc;
   7.121 +	} else {
   7.122 +		q->tail->next = proc;
   7.123 +	}
   7.124 +
   7.125 +	proc->next = 0;
   7.126 +	proc->prev = q->tail;
   7.127 +	q->tail = proc;
   7.128 +}
   7.129 +
   7.130 +static void ins_front(struct proc_list *q, struct process *proc)
   7.131 +{
   7.132 +	if(EMPTY(*q)) {
   7.133 +		q->tail = proc;
   7.134 +	} else {
   7.135 +		q->head->prev = proc;
   7.136 +	}
   7.137 +
   7.138 +	proc->next = q->head;
   7.139 +	proc->prev = 0;
   7.140 +	q->head = proc;
   7.141 +}
   7.142 +
   7.143 +static void remove(struct proc_list *q, struct process *proc)
   7.144 +{
   7.145 +	if(proc->prev) {
   7.146 +		proc->prev->next = proc->next;
   7.147 +	}
   7.148 +	if(proc->next) {
   7.149 +		proc->next->prev = proc->prev;
   7.150 +	}
   7.151 +	if(q->head == proc) {
   7.152 +		q->head = proc->next;
   7.153 +	}
   7.154 +	if(q->tail == proc) {
   7.155 +		q->tail = proc->prev;
   7.156 +	}
   7.157 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/src/sched.h	Mon Aug 01 06:45:29 2011 +0300
     8.3 @@ -0,0 +1,12 @@
     8.4 +#ifndef SCHED_H_
     8.5 +#define SCHED_H_
     8.6 +
     8.7 +#include "proc.h"
     8.8 +
     8.9 +void schedule(void);
    8.10 +
    8.11 +int add_proc(int pid, enum proc_state state);
    8.12 +int block_proc(int pid);
    8.13 +int unblock_proc(int pid);
    8.14 +
    8.15 +#endif	/* SCHED_H_ */
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/src/syscall.c	Mon Aug 01 06:45:29 2011 +0300
     9.3 @@ -0,0 +1,56 @@
     9.4 +#include <stdio.h>
     9.5 +#include "syscall.h"
     9.6 +#include "intr.h"
     9.7 +#include "proc.h"
     9.8 +#include "sched.h"
     9.9 +#include "timer.h"
    9.10 +
    9.11 +static int (*sys_func[NUM_SYSCALLS])();
    9.12 +
    9.13 +static void syscall(int inum, struct intr_frame *frm);
    9.14 +
    9.15 +static int sys_exit(int status);
    9.16 +static int sys_hello(void);
    9.17 +static int sys_sleep(int sec);
    9.18 +
    9.19 +void init_syscall(void)
    9.20 +{
    9.21 +	sys_func[SYS_EXIT] = sys_exit;
    9.22 +	sys_func[SYS_HELLO] = sys_hello;
    9.23 +	sys_func[SYS_SLEEP] = sys_sleep;
    9.24 +
    9.25 +	interrupt(SYSCALL_INT, syscall);
    9.26 +}
    9.27 +
    9.28 +static void syscall(int inum, struct intr_frame *frm)
    9.29 +{
    9.30 +	int idx = frm->regs.eax;
    9.31 +
    9.32 +	if(idx < 0 || idx >= NUM_SYSCALLS) {
    9.33 +		printf("invalid syscall: %d\n", idx);
    9.34 +		return;
    9.35 +	}
    9.36 +
    9.37 +	frm->regs.eax = sys_func[idx](frm->regs.ebx, frm->regs.ecx, frm->regs.edx, frm->regs.esi, frm->regs.edi);
    9.38 +	schedule();
    9.39 +}
    9.40 +
    9.41 +static int sys_exit(int status)
    9.42 +{
    9.43 +	return -1;	/* not implemented yet */
    9.44 +}
    9.45 +
    9.46 +static int sys_hello(void)
    9.47 +{
    9.48 +	/*printf("process %d says hello!\n", get_current_pid());*/
    9.49 +	return 0;
    9.50 +}
    9.51 +
    9.52 +static int sys_sleep(int sec)
    9.53 +{
    9.54 +	int pid = get_current_pid();
    9.55 +	/*printf("process %d will sleep for %d sec\n", pid, sec);*/
    9.56 +	start_timer(sec * 1000, (timer_func_t)unblock_proc, (void*)pid);
    9.57 +	block_proc(pid);
    9.58 +	return 0;
    9.59 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/src/syscall.h	Mon Aug 01 06:45:29 2011 +0300
    10.3 @@ -0,0 +1,17 @@
    10.4 +#ifndef SYSCALL_H_
    10.5 +#define SYSCALL_H_
    10.6 +
    10.7 +#define SYSCALL_INT		0x80
    10.8 +
    10.9 +/* when we get rid of test_proc.S we'll turn this into an enum */
   10.10 +#define SYS_EXIT		0
   10.11 +#define SYS_HELLO		1
   10.12 +#define SYS_SLEEP		2
   10.13 +
   10.14 +#define NUM_SYSCALLS	3
   10.15 +
   10.16 +#ifndef ASM
   10.17 +void init_syscall(void);
   10.18 +#endif
   10.19 +
   10.20 +#endif	/* SYSCALL_H_ */
    11.1 --- a/src/sysnum.h	Sat Jul 30 07:35:53 2011 +0300
    11.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.3 @@ -1,10 +0,0 @@
    11.4 -#ifndef SYSNUM_H_
    11.5 -#define SYSNUM_H_
    11.6 -
    11.7 -#define SYSCALL_INT		0x80
    11.8 -
    11.9 -#define SYS_EXIT		0
   11.10 -#define SYS_HELLO		1
   11.11 -#define SYS_SLEEP		2
   11.12 -
   11.13 -#endif	/* SYSNUM_H_ */
    12.1 --- a/src/test_proc.S	Sat Jul 30 07:35:53 2011 +0300
    12.2 +++ b/src/test_proc.S	Mon Aug 01 06:45:29 2011 +0300
    12.3 @@ -1,4 +1,5 @@
    12.4 -#include <sysnum.h>
    12.5 +#define ASM
    12.6 +#include <syscall.h>
    12.7  
    12.8  	.text
    12.9  	.globl test_proc
    13.1 --- a/src/timer.c	Sat Jul 30 07:35:53 2011 +0300
    13.2 +++ b/src/timer.c	Mon Aug 01 06:45:29 2011 +0300
    13.3 @@ -3,6 +3,8 @@
    13.4  #include "intr.h"
    13.5  #include "asmops.h"
    13.6  #include "timer.h"
    13.7 +#include "proc.h"
    13.8 +#include "sched.h"
    13.9  #include "config.h"
   13.10  
   13.11  /* frequency of the oscillator driving the 8254 timer */
   13.12 @@ -39,9 +41,24 @@
   13.13  #define CMD_MODE_BCD		1
   13.14  
   13.15  
   13.16 +#define MSEC_TO_TICKS(ms)	((ms) * TICK_FREQ_HZ / 1000)
   13.17 +
   13.18 +struct timer_event {
   13.19 +	int dt;	/* remaining ticks delta from the previous event */
   13.20 +
   13.21 +	void (*callback)(void*);
   13.22 +	void *cbarg;
   13.23 +
   13.24 +	struct timer_event *next;
   13.25 +};
   13.26 +
   13.27 +
   13.28  static void intr_handler();
   13.29  
   13.30  
   13.31 +static struct timer_event *evlist;
   13.32 +
   13.33 +
   13.34  void init_timer(void)
   13.35  {
   13.36  	/* calculate the reload count: round(osc / freq) */
   13.37 @@ -62,11 +79,101 @@
   13.38  	interrupt(IRQ_TO_INTR(0), intr_handler);
   13.39  }
   13.40  
   13.41 +int start_timer(unsigned long msec, timer_func_t cbfunc, void *cbarg)
   13.42 +{
   13.43 +	int ticks, tsum, istate;
   13.44 +	struct timer_event *ev, *node;
   13.45 +
   13.46 +	printf("start_timer(%lu)\n", msec);
   13.47 +
   13.48 +	if((ticks = MSEC_TO_TICKS(msec)) <= 0) {
   13.49 +		cbfunc(cbarg);
   13.50 +		return 0;
   13.51 +	}
   13.52 +
   13.53 +	if(!(ev = malloc(sizeof *ev))) {
   13.54 +		printf("start_timer: failed to allocate timer_event structure\n");
   13.55 +		return -1;
   13.56 +	}
   13.57 +	ev->callback = cbfunc;
   13.58 +	ev->cbarg = cbarg;
   13.59 +
   13.60 +	istate = get_intr_state();
   13.61 +	disable_intr();
   13.62 +
   13.63 +	/* insert at the beginning */
   13.64 +	if(!evlist || ticks <= evlist->dt) {
   13.65 +		ev->next = evlist;
   13.66 +		evlist = ev;
   13.67 +
   13.68 +		ev->dt = ticks;
   13.69 +		if(ev->next) {
   13.70 +			ev->next->dt -= ticks;
   13.71 +		}
   13.72 +		set_intr_state(istate);
   13.73 +		return 0;
   13.74 +	}
   13.75 +
   13.76 +	tsum = evlist->dt;
   13.77 +	node = evlist;
   13.78 +
   13.79 +	while(node->next && ticks > tsum + node->next->dt) {
   13.80 +		tsum += node->next->dt;
   13.81 +		node = node->next;
   13.82 +	}
   13.83 +
   13.84 +	ev->next = node->next;
   13.85 +	node->next = ev;
   13.86 +
   13.87 +	/* fix the relative times */
   13.88 +	ev->dt = ticks - tsum;
   13.89 +	if(ev->next) {
   13.90 +		ev->next->dt -= ev->dt;
   13.91 +	}
   13.92 +
   13.93 +	set_intr_state(istate);
   13.94 +	return 0;
   13.95 +}
   13.96 +
   13.97  /* This will be called by the interrupt dispatcher approximately
   13.98   * every 1/250th of a second, so it must be extremely fast.
   13.99   * For now, just increasing a tick counter will suffice.
  13.100   */
  13.101 -static void intr_handler()
  13.102 +static void intr_handler(int inum)
  13.103  {
  13.104 +	int istate;
  13.105 +	struct process *cur_proc;
  13.106 +
  13.107  	nticks++;
  13.108 +
  13.109 +	printf("TICKS: %d\n", nticks);
  13.110 +
  13.111 +	istate = get_intr_state();
  13.112 +	disable_intr();
  13.113 +
  13.114 +	/* find out if there are any timers that have to go off */
  13.115 +	if(evlist) {
  13.116 +		evlist->dt--;
  13.117 +
  13.118 +		while(evlist->dt <= 0) {
  13.119 +			struct timer_event *ev = evlist;
  13.120 +			evlist = evlist->next;
  13.121 +
  13.122 +			printf("timer going off!!!\n");
  13.123 +			ev->callback(ev->cbarg);
  13.124 +			free(ev);
  13.125 +		}
  13.126 +	}
  13.127 +
  13.128 +	if((cur_proc = get_current_proc())) {
  13.129 +		if(--cur_proc->ticks_left <= 0) {
  13.130 +			/* since schedule will not return, we have to notify
  13.131 +			 * the PIC that we're done with the IRQ handling
  13.132 +			 */
  13.133 +			end_of_irq(INTR_TO_IRQ(inum));
  13.134 +			schedule();
  13.135 +		}
  13.136 +	}
  13.137 +
  13.138 +	set_intr_state(istate);
  13.139  }
    14.1 --- a/src/timer.h	Sat Jul 30 07:35:53 2011 +0300
    14.2 +++ b/src/timer.h	Mon Aug 01 06:45:29 2011 +0300
    14.3 @@ -1,8 +1,12 @@
    14.4  #ifndef _TIMER_H_
    14.5  #define _TIMER_H_
    14.6  
    14.7 +typedef void (*timer_func_t)(void*);
    14.8 +
    14.9  unsigned long nticks;
   14.10  
   14.11  void init_timer(void);
   14.12  
   14.13 +int start_timer(unsigned long msec, timer_func_t cbfunc, void *cbarg);
   14.14 +
   14.15  #endif	/* _TIMER_H_ */
    15.1 --- a/src/vm.c	Sat Jul 30 07:35:53 2011 +0300
    15.2 +++ b/src/vm.c	Mon Aug 01 06:45:29 2011 +0300
    15.3 @@ -37,7 +37,7 @@
    15.4  uint32_t get_fault_addr(void);
    15.5  
    15.6  static void coalesce(struct page_range *low, struct page_range *mid, struct page_range *high);
    15.7 -static void pgfault(int inum, uint32_t err);
    15.8 +static void pgfault(int inum, struct intr_frame *frm);
    15.9  static struct page_range *alloc_node(void);
   15.10  static void free_node(struct page_range *node);
   15.11  
   15.12 @@ -457,18 +457,18 @@
   15.13  	}
   15.14  }
   15.15  
   15.16 -static void pgfault(int inum, uint32_t err)
   15.17 +static void pgfault(int inum, struct intr_frame *frm)
   15.18  {
   15.19  	printf("~~~~ PAGE FAULT ~~~~\n");
   15.20  
   15.21  	printf("fault address: %x\n", get_fault_addr());
   15.22  
   15.23 -	if(err & PG_PRESENT) {
   15.24 -		if(err & 8) {
   15.25 +	if(frm->err & PG_PRESENT) {
   15.26 +		if(frm->err & 8) {
   15.27  			printf("reserved bit set in some paging structure\n");
   15.28  		} else {
   15.29 -			printf("%s protection violation ", (err & PG_WRITABLE) ? "write" : "read");
   15.30 -			printf("in %s mode\n", err & PG_USER ? "user" : "kernel");
   15.31 +			printf("%s protection violation ", (frm->err & PG_WRITABLE) ? "write" : "read");
   15.32 +			printf("in %s mode\n", frm->err & PG_USER ? "user" : "kernel");
   15.33  		}
   15.34  	} else {
   15.35  		printf("page not present\n");