是什么会导致preempt_count更改或使工作队列在原子上下文中运行?

jos*_*sec 2 linux-kernel

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

从一次崩溃到下一次崩溃,内核日志消息可能有所不同,但是在某些情况下,我得到以下信息:

<4>huh, entered c90390a8 with preempt_count 0000010d, exited with c0340000?
Run Code Online (Sandbox Code Playgroud)

生成此日志的代码来自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();
            }
Run Code Online (Sandbox Code Playgroud)

为了使这种情况发生,必须发生什么(显然preempt_count已更改,但是可能导致该情况)?

崩溃的另一个症状是,我scheduling while atomic在工作队列中看到i2c的时间(肯定不是原子的,对吧?)。是什么原因造成的?

我认为这篇文章是长篇大论,但是我现在真的只是在寻找任何需要解决的问题。

小智 5

只是从我的脑海中回答:“ preempt_count”是一个32位字段,出于各种目的,该字段分为多个子位字段。O'Reilly的《了解Linux内核》中详细介绍了子位字段。再次,从我的头顶上,我不知道“ c0340000”代表什么。但是,由于您以“ 0000010d”开头,并且本应以“ 0000010d”结尾,所以您的计时器代码所做的一切都很混乱。

一个常见的原因是您的计时器代码是否执行了spin_lock_bh()之类的操作,却忘记执行spin_unlock_bh()了。但这通常导致preempt_count起始值和结束值之间只有1位的差异。但就您而言,您的开始和结束值显示出巨大的变化。

麦可