preempt_countが原子コンテキストで実行するために変更またはワークキューを引き起こす原因は何ですか?

私はいくつかのモジュール作業をしていて、ランダムに(通常は起動後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を実行している間に atomic のスケジューリングを見ていることです。これは何が原因でしょうか?

私はこのポストはロングショットだと思っていますが、私は実際にこの時点で何かトラブルシューティングを探しています。

1

1 答え

私の頭の上からちょうど答えてください: "preempt_count"は32ビットフィールドで、さまざまな目的のためにサブビットフィールドに分割されています。サブビットフィールドは、O'Reillyの「Linuxカーネルについて」を参照してください。再び、私の頭の上から、私は "c0340000"が何を表すのか分からない。しかし、あなたが "0000010d"で始まって "0000010d"で終わったはずなので、あなたのタイマーコードが何をしていたとしてもかなり混乱しています。

1つの一般的な原因は、あなたのタイマーコードがspin_lock_bh()のようなことをしたが、spin_unlock_bh()を忘れた場合です。しかし、それは通常、preempt_countの開始と終了の値のちょうど1ビットの差になります。しかし、あなたの場合、開始値と終了値は大きな変化を示します。

マイケル

3
追加された
終了値はほとんどアドレスのように見えます。おそらく、タイマーで実行されたコードは、メモリ内のランダムな場所に書き込んでいますか?私が作業していたモジュールにはタイマーがありませんでしたが、ワークキューがありました。この問題が発生したとき、スケジューリングのためのメッセージがワークキューからアトミックに表示されます。とにかく、私はあなたのコメントに感謝:)
追加された 著者 josec,
うーん、ええ、私はc0340000がアドレスかもしれないと思います。しかし、最後の4桁の16進数がすべて0であるという事実は、アドレスにとってはきちんとしているようです。いずれの場合でも、 "cat/proc/modules"を実行して、ドライバアドレスのいずれかにc0340000
追加された 著者 mwang25,