x
x
xv6-sifive文档
Search…
⌃K

时钟中断

RISC-V的CPU在一定的时间段就会触发一次时钟中断,RISC-V希望时钟中断能在M态处理而不是在S态处理.我们选择在一个特殊的方法来处理时钟中断.
start.c中,我们设置了把所有中断都放在S态进行处理.但是我们在timerinit函数中创建了一个专属于时钟中断的处理模式,在这个函数中,我们主要是获得了时钟中断的锁.
当时钟中断产生的时候,我们一般认为这个中断是一个设备中断:在devintr函数中我们看到了时钟中断的处理逻辑:
else if (0x8000000000000005L == scause) {
timer_tick();
return 2;
}
每一次时钟中断都会调用timer_tick函数:
  • 通知因为sleep导致睡眠的进程.
  • 设置下一次时钟中断的时间.
void timer_tick() {
acquire(&tickslock);
ticks++;
wakeup(&ticks);
release(&tickslock);
set_next_timeout();
}
set_next_timeout函数中,我们通过sbi接口设置了下一次时钟中断的时间:
void
set_next_timeout() {
// There is a very strange bug,
// if comment the `printf` line below
// the timer will not work.
// this bug seems to disappear automatically
// printf("");
sbi_set_timer(r_time() + INTERVAL);
}
为了适配进程的时间计数,我们在每一次时钟中断的时候添加了proc_tick()函数:
void proc_tick(void) {
// runnable
struct proc* p;
struct proc* np;
for(p = proc; p < &proc[NPROC]; p++) {
acquire(&p->lock);
p->proc_tms.utime += 1;
p->proc_tms.stime += 1;
np = p->parent;
while(np){
np->proc_tms.cstime += p->proc_tms.stime + p->proc_tms.cstime;
np->proc_tms.cutime += p->proc_tms.utime + p->proc_tms.cutime;
np = np->parent;
}
release(&p->lock);
}
}
这个函数我们主要是处理tms结构体里面的数据:
struct tms {
uint64 utime; // user time
uint64 stime; // system time
uint64 cutime; // user time of children
uint64 cstime; // system time of children
};
我们在每一个时钟周期对tms进行一次处理即可.