diff options
author | Robert Morris <[email protected]> | 2019-07-01 13:46:11 -0400 |
---|---|---|
committer | Robert Morris <[email protected]> | 2019-07-01 13:46:11 -0400 |
commit | 0498bfd15937d64599b8c63948907a8b60e5d6ae (patch) | |
tree | f65d35cd340235216dbd9628184ef3d9547685b5 | |
parent | c34bd3d1671f1f6e1b50614c22fbd0c83f504959 (diff) | |
download | xv6-labs-0498bfd15937d64599b8c63948907a8b60e5d6ae.tar.gz xv6-labs-0498bfd15937d64599b8c63948907a8b60e5d6ae.tar.bz2 xv6-labs-0498bfd15937d64599b8c63948907a8b60e5d6ae.zip |
timer interrupt in the kernel -> yield
-rw-r--r-- | kernel/kernelvec.S | 2 | ||||
-rw-r--r-- | kernel/trap.c | 17 |
2 files changed, 15 insertions, 4 deletions
diff --git a/kernel/kernelvec.S b/kernel/kernelvec.S index 4f52688..e9b0ced 100644 --- a/kernel/kernelvec.S +++ b/kernel/kernelvec.S @@ -47,7 +47,7 @@ kernelvec: ld ra, 0(sp) ld sp, 8(sp) ld gp, 16(sp) - ld tp, 24(sp) + // not this, in case we moved CPUs: ld tp, 24(sp) ld t0, 32(sp) ld t1, 40(sp) ld t2, 48(sp) 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, |