summaryrefslogtreecommitdiff
path: root/kernel/trap.c
diff options
context:
space:
mode:
authorRobert Morris <[email protected]>2019-07-01 13:46:11 -0400
committerRobert Morris <[email protected]>2019-07-01 13:46:11 -0400
commit0498bfd15937d64599b8c63948907a8b60e5d6ae (patch)
treef65d35cd340235216dbd9628184ef3d9547685b5 /kernel/trap.c
parentc34bd3d1671f1f6e1b50614c22fbd0c83f504959 (diff)
downloadxv6-labs-0498bfd15937d64599b8c63948907a8b60e5d6ae.tar.gz
xv6-labs-0498bfd15937d64599b8c63948907a8b60e5d6ae.tar.bz2
xv6-labs-0498bfd15937d64599b8c63948907a8b60e5d6ae.zip
timer interrupt in the kernel -> yield
Diffstat (limited to 'kernel/trap.c')
-rw-r--r--kernel/trap.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/kernel/trap.c b/kernel/trap.c
index 586f123..06fc4b3 100644
--- a/kernel/trap.c
+++ b/kernel/trap.c
@@ -121,12 +121,14 @@ usertrapret(void)
((void (*)(uint64,uint64))TRAMPOLINE)(TRAMPOLINE - PGSIZE, satp);
}
-// interrupts and exceptions from kernel code go here,
+// interrupts and exceptions from kernel code go here via kernelvec,
// on whatever the current kernel stack is.
// must be 4-byte aligned to fit in stvec.
void
kerneltrap()
{
+ int which_dev = 0;
+ uint64 sepc = r_sepc();
uint64 sstatus = r_sstatus();
uint64 scause = r_scause();
@@ -135,11 +137,20 @@ kerneltrap()
if(intr_get() != 0)
panic("kerneltrap: interrupts enabled");
- if(devintr() == 0){
- printf("scause 0x%p\n", scause);
+ if((which_dev = devintr()) == 0){
+ printf("scause %p\n", scause);
printf("sepc=%p stval=%p\n", r_sepc(), r_stval());
panic("kerneltrap");
}
+
+ // give up the CPU if this is a timer interrupt.
+ if(which_dev == 2 && myproc() != 0 && myproc()->state == RUNNING)
+ yield();
+
+ // the yield() may have caused some traps to occur,
+ // so restore trap registers for use by kernelvec.S's sepc instruction.
+ w_sepc(sepc);
+ w_sstatus(sstatus);
}
// check if it's an external interrupt or software interrupt,