linux kernel kthread调度问题,调度不及时
讨论的前提
在一个项目中,在中断里去唤醒一个kthread做一些事,但是发现kthread执行的动作会有延迟,我们初步怀疑是丢中断导致。看下代码:
典型的kthread循环
while (!kthread_should_stop()) {
dosomething();
set_current_state(TASK_INTERRUPTIBLE);
schedule();
}
__set_current_state(TASK_RUNNING);
从代码中可以看到,当没事的时候,调度出去,
在中断到来的时候,我们调用wake_up_process去唤醒这个kthread来执行dosomething函数
这样看来没什么问题。但是发现中断频繁的时候,会有延迟性的问题,dosomething不能及时执行,比如取fifo,发现fifo里的东西并没有及时取走。
问题就出在dosomething里面,假如这个函数执行的时间略长一些(相对时间长一些也无可厚非,本来是一个kthread),但是假如dosomething快结束,但是还未调用到set_current_state(TASK_INTERRUPTIBLE);的时候,来了irq,调用了wake_up_process,需要kthread再执行一次。
不好意思,紧接着set_current_state(TASK_INTERRUPTIBLE);会让kthread的state变成TASK_INTERRUPTIBLE,使得调度器把当前kthread置于睡眠状态,直到下一次中断的到来,才会唤醒继续执行,这里就产生了时间差。
如何修改
既然知道了原因,只要调整下代码即可,我的做法是将set_current_state(TASK_INTERRUPTIBLE)放到schedule后面,这样避免dosomething执行过程中产生的wake_up事件的丢失。
set_current_state(TASK_INTERRUPTIBLE);
while (!kthread_should_stop()) {
dosomething();
schedule();
set_current_state(TASK_INTERRUPTIBLE);
}