什么可能导致preempt_count更改或workqueue在原子上下文中运行?

时间:2012-02-06 16:49:54

标签: linux-kernel

我一直在做一些模块工作,我发生了随机发生的崩溃(通常在启动后10小时内)。

内核日志消息可能因崩溃而异,但在某些情况下我会得到这个:

<4>huh, entered c90390a8 with preempt_count 0000010d, exited with c0340000?

生成此日志的代码来自2.6.14内核kernel / timer.c:

            int preempt_count = preempt_count();
            fn(data);
            if (preempt_count != preempt_count()) {
                printk(KERN_WARNING "huh, entered %p "
                       "with preempt_count %08x, exited"
                       " with %08x?\n",
                       fn, preempt_count,
                       preempt_count());
                BUG();
            }

要发生这种情况,必须发生什么事情(显然preempt_count已更改,但可能会导致这种情况发生?)

崩溃的另一个症状是我在从工作队伍中做i2c时看到scheduling while atomic(当然不应该是原子的,对吧?)。可能导致这种情况的原因是什么?

我认为这篇文章是一个很长的镜头,但我真的只是在寻找任何可以解决的问题。

1 个答案:

答案 0 :(得分:4)

刚才从头顶回答:“preempt_count”是一个32位字段,为了各种目的,它们被分成子位字段。 O'Reilly的了解Linux内核详细介绍了子位字段。再一次,在我的头顶,我不知道“c0340000”代表什么。但是既然你开始使用“0000010d”,并且应该以“0000010d”结束,那么无论你的定时器代码做了什么都搞砸了。

一个常见的原因是你的计时器代码做了类似spin_lock_bh()的事情,但是忘了做一个spin_unlock_bh()。但这通常会导致起始和结束preempt_count值之间只有1位差异。但在您的情况下,您的起始值和结束值会发生巨大变化。

迈克尔