(stranger) 10-03-11 13:09
| 请教一个hrtimer的问题 | |
|
hrtimer_enqueue_reprogram中重新设定下一次中断发生的时间以后,还会调用raise_softirq_irqoff(HRTIMER_SOFTIRQ);设置相应的软中断,并唤醒softirqd。 为什么要这样设置呢?此时对应的hrtimer并没有发生。
为什么不在时钟中断的处理函数中,设置raise_softirq_irqoff(HRTIMER_SOFTIRQ)呢? 文章选项: |
(addict) 10-03-11 13:40
| Re: 请教一个hrtimer的问题 [] | |
|
这个是由hrtimer的执行环境决定的。 hrtimer expired后的执行在hrtimer_interrupt or softirq 两种环境里。 so,如果是 softirq环境的话,就得使能HRTIMER_SOFTIRQ软中断,在软中断执行点调用 run_hrtimer_softirq 手动触发 hrtimer_interrupt.
"为什么不在时钟中断的处理函数中,设置raise_softirq_irqoff(HRTIMER_SOFTIRQ)呢?" == 你说的“时钟中断的处理函数”是指scheduler_tick()还是hrtimer_interrupt()? 如果是前者的话,原因是粒度太大了,比不上hrtimer 的精度。
-------------------- 做kernel,求内推,长期有效
文章选项: |
(stranger) 10-03-11 15:49
| Re: 请教一个hrtimer的问题 [] | |
|
也许我没问清楚: hrtimer_enqueue_reprogram的定义: static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer, struct hrtimer_clock_base *base) { if (base->cpu_base->hres_active && hrtimer_reprogram(timer, base)) { spin_unlock(&base->cpu_base->lock); raise_softirq_irqoff(HRTIMER_SOFTIRQ); spin_lock(&base->cpu_base->lock); return 1; } return 0; } hrtimer_reprogram已经重新设置了中断,假设是50us以后,中断产生,而在时钟中断处理函数中,本来就会在中断上下文中处理hrtimer,为什么要手动设置raise_softirq_irqoff(HRTIMER_SOFTIRQ);? 而且,raise_softirq_irqoff中会唤醒softirqd,这是硬件时钟中断还没有到来,就已经执行这个定时器,不是提前了吗? 文章选项: |
(addict) 10-03-11 19:44
| Re: 请教一个hrtimer的问题 [] | |
|
不知道这么回答可不可以:
假如这个hrtimer要在软中断环境执行且过期时Tick中断还没有到怎么办呢?
每一次设置hrtimer的时候激活softirq,保证hardirq中断退出时给softirq一个执行hrtimer的机会。 当然在scheduler_tick时会检测 过期的hrtimer,但有可能已经太迟了...
-------------------- 做kernel,求内推,长期有效
文章选项: |
(stranger) 10-03-12 17:06
| Re: 请教一个hrtimer的问题 [] | |
|
我们还是情景分析一下吧,先明确一下前提:Kernel是2.6.29,而且make menuconfig选中tickless(也就是NO_HZ宏定义打开)。 我谈谈我的理解: 假设一个nanosleep(50), 此时内核会将这个定时器加入到hrtimers中,当发现这是最近一个到期定时器的时候,将这个时间与下一个tick发生时间比较,如果比下一个tick近,则调用hrtimer_enqueue_reprogram重新设置时钟中断,要求在50ns以后产生中断。 在50ns以后,中断发生,进入时钟处理函数tick_period。 tick_period->update_process_times->run_local_timers->hrtimer_run_queues()中会直接处理一遍所有到期的高精度定时器。然后设置普通精度定时器的软中断。
如果我以上的理解是正确的,那么hrtimer_enqueue_reprogram中间为什么要调用raise_softirq_irqoff(HRTIMER_SOFTIRQ)来唤醒hrtimer的软中断。
因为50ns以后明明会有一个硬中断产生,而且会直接处理到期定时。
文章选项: |
(addict) 10-03-12 18:11
| Re: 请教一个hrtimer的问题 [] | |
|
兄弟,好像不是这个样子的。。。 我的理解是: 50ns后进入 hrtimer_interrupt()是硬中断环境,立即退出 --> 执行软中断(这个时候离tick中断还很远)-->处理hrtimer.
-------------------- 做kernel,求内推,长期有效
文章选项: |
(stranger) 10-03-15 10:16
| Re: 请教一个hrtimer的问题 [] | |
|
感谢你的回复,我又仔细看了一下代码,你说的对2.6.27是对的,但是对于2.6.29以后,就不完全对了。 2.6.27的hrtimer_interrupt处理流程是: 1.找出所有到期定时器,加到cb_pending 2.raise_softirq(HRTIMER_SOFTIRQ); 3.规划下一次的定时器 而2.6.29以后则是 1.找出所有到期hr定时器,直接执行 2.规划下一次定时器 而没有raise_softirq(HRTIMER_SOFTIRQ)
文章选项: |
(addict) 10-03-15 12:04
| Re: 请教一个hrtimer的问题 [] | |
|
再回答1楼的问题把, 刚看了下代码,我前面的回答有部分可能是错的。 我再看看代码,咣当咣当。。。
-------------------- 做kernel,求内推,长期有效
文章选项: |
(addict) 10-03-15 12:32
| Re: 请教一个hrtimer的问题 [] | |
|
hrtimer_enqueue_reprogram()这个函数在重新启用一个hrtimer且此hrtimer变成红黑树leftmost的时候被调用。 说明这是个即将过期的hrtimer。
重新program 硬件的register后,启用设置了softirq的pending标志,说明在任何下一个软中断的环境,都会执行HRTIMER_SOFTIRQ,他的作用是手动触发一个interrupt,即调用hrtimer_interrupt().
最新的代码里硬中断处理函数hrtimer_interrupt()会检测leftmost的hrtimer是否过期并执行。现在是软中断环境也尝试去做同样的事情。有一点不同的是,参数wakeup,如果设置且当前是非中断上下文,要唤醒softirqd去处理,否则只是置softirq_pending标志位。
按说设置了硬件寄存器应该等硬中断的,现在软中断环境里做重复(补充)的事情,为什么呢? 我不敢说是“禁timer硬中断的情况下使用"这个结论。。。
-------------------- 做kernel,求内推,长期有效
文章选项: |