del_timer_sync不能在中断上下文调?
1. 内核对中断上下文的定义是什么?禁止抢占就可以认为是中断上下文,而不是狭义上的softirq和irq吧。
2. del_timer_sync不能再中断上下文调用? * Note: For !irqsafe timers, you must not hold locks that are held in
* interrupt context while calling this function. Even if the lock has
* nothing to do with the timer in question.Here's why:
*
* CPU0 CPU1
* ---- ----
* <SOFTIRQ>
* call_timer_fn();
* base->running_timer = mytimer;
*spin_lock_irq(somelock);
* <IRQ>
* spin_lock(somelock);
*del_timer_sync(mytimer);
* while (base->running_timer == mytimer);
*
* Now del_timer_sync() will never return and never release somelock.
* The interrupt on the other CPU is waiting to grab somelock but
* it has interrupted the softirq that CPU0 is waiting to finish.
*
* The function returns whether it has deactivated a pending timer or not.
删除定时器就是detach_timer,看内核对del_timer_sync的实现,它没有主动调度,如果按照上面的用法,是会死锁。
但是如果我这样用:
* CPU0 CPU1
* ---- ----
* <SOFTIRQ>
* call_timer_fn();
* base->running_timer = mytimer;
*spin_lock_irq(lock_A);
* <IRQ>
* spin_lock(lock_B);
*del_timer_sync(mytimer);
* while (base->running_timer == mytimer);保证该锁不会死锁,应该好像也是可以用的? 第一个问题:
关抢占不属于中断上下文。但软硬中断里头都属于中断上下文。原因请见:
#define in_irq() (hardirq_count())
#define in_softirq() (softirq_count())
#define in_interrupt() (irq_count())
#define hardirq_count() (preempt_count() & HARDIRQ_MASK)
#define softirq_count() (preempt_count() & SOFTIRQ_MASK)
#define irq_count() (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
我们的判断标准就是in_interrupt()
第二个问题:
还没有想明白,不过:
* Synchronization rules:
1. Callers must prevent restarting of the timer, otherwise this function is meaningless.
2. It must not be called from interrupt contexts.
3. The caller must not hold locks which would preventcompletion of the timer's handler.
4. The timer's handler must not calladd_timer_on().
这4个条件好像要同时满足,你一开始于的这个场景是只这里的第3条。而并不是不能在中段里头用的原因。
反过来证明,在你的场景里头,就算是CPU 0不是在中断里头调用del_timer_sync,死锁也一样会发生。 看到这个贴:https://lkml.org/lkml/2011/6/16/224
突然想明白了。
如果在CPU0 上执行TimerA, 正在执行时,被中断,此时调用del_timer_sync就会自死锁。因为中断不返回,这个TimerA又不可能完成,而不完成,del_timer_sync又不可能返回。要知道__run_timers是在放了锁的情况下去运行Timer的。 本帖最后由 镇水铁牛 于 2014-11-28 06:34 编辑
回复 3# Tinnal
如果在CPU0 上执行TimerA, 正在执行时,被中断,此时调用del_timer_sync就会自死锁。因为中断不返回,这个TimerA又不可能完成,而不完成,del_timer_sync又不可能返回。
【】如果在CPU0 上执行TimerA(在CPU0的软中断处理上下文), 正在执行时,被中断,只有CPU0的硬中断会打断它吧(软中断是不会打断软中断的),理论上不会在硬中断中调用del_timer_sync。其实最关键的是 The caller must not hold locks which would preventcompletionof the timer's handler.
要知道__run_timers是在放了锁的情况下去运行Timer的。
【】是的,内核在很多中断处理都是开中断和无锁的。
本帖最后由 Tinnal 于 2014-11-28 09:17 编辑
回复 4# 镇水铁牛
只有CPU0的硬中断会打断它吧(软中断是不会打断软中断的),理论上不会在硬中断中调用del_timer_sync
首先,这不是一个理论,没有去证明。
其次,我们甚至不能假定。
就如https://lkml.org/lkml/2011/6/16/224这个BUG一下。on_each_cpu、smp_call_function等,一个不注意,就已经是硬中断环境了。
另人在函数头明确声明的约束,最好整改一下程序吧,就算现在你想近尽法说它们的这些约束你不涉及,内核的演变也不能保证你永远不涉及,还是尽量不要去违背,https://lkml.org/lkml/2011/6/16/224最终也改了。
页:
[1]