linux kernel 工程师
全部博文(99)
分类: LINUX
2014-02-05 17:51:28
__local_bh_disable(SOFTIRQ_OFFSET)/__local_bh_enable(SOFTIRQ_OFFSET)
仅仅是增加/减少抢占计数, 这两个函数被__do_softirq()调用,应当不会被kernel线程来调用
static void __local_bh_enable(unsigned int cnt)
{
WARN_ON_ONCE(in_irq());
WARN_ON_ONCE(!irqs_disabled());
if (softirq_count() == cnt)
trace_softirqs_on((unsigned long)__builtin_return_address(0));
sub_preempt_count(cnt); /* 减少抢占计数 */
}
static inline void __local_bh_disable(unsigned long ip, unsigned int cnt)
{
add_preempt_count(cnt); /* 增加抢占计数 */
barrier();
}
--------------------------------------------------------------------
在线程环境下调用local_bh_enable时,需要执行被耽误的softirq
static inline void _local_bh_enable_ip(unsigned long ip)
{
WARN_ON_ONCE(in_irq() || irqs_disabled());
#ifdef CONFIG_TRACE_IRQFLAGS
local_irq_disable();
#endif
/*
* Are softirqs going to be turned on now:
*/
if (softirq_count() == SOFTIRQ_DISABLE_OFFSET)
trace_softirqs_on(ip);
/*
* Keep preemption disabled until we are done with
* softirq processing:
*/
sub_preempt_count(SOFTIRQ_DISABLE_OFFSET - 1); /* 此时抢占计数为1,还不能被抢占 */
/* 但在执行softirq的callback函数时, 可以被中断和softirq打断 */
if (unlikely(!in_interrupt() && local_softirq_pending()))
do_softirq(); /* 这里是线程上下文,不是中断上下文,所以需要调用do_softirq(这个函数里面有先关闭中断的操作) */
/* 因为线程里面禁止softirq,会导致softirq的推迟,所以在使能softirq后,主动执行已经被推迟的softirq */
dec_preempt_count(); /* 抢占计数再减1,此时应当变为0,开启抢占 */
#ifdef CONFIG_TRACE_IRQFLAGS
local_irq_enable();
#endif
preempt_check_resched();
}