まあ、あなたは、すべての発明(またはこの場合は研究)の母親である必要性について、彼らが言うことを知っています。私は本当にこの答えが必要で、kernel/workqueue.cを掘り下げて得ました。答えはDocumentation/workqueue.txt
と組み合わされたdoc commentsにほとんど含まれていますが、Concurrency Managed Workqueue(cmwq)サブシステムで仕様全体を読んでいないと、明確なスペルはありません。
短い答え
ウィル[あなたのコードは] delayed_workをできるだけ早く実行されることを保証しますか? (下記の注意点が)
はい
作業がすでに実行されている状況で何が起こる
?
他の作業が既に(原因である、または遅延作業)そのワークキューにキューに入れられたが、それは、後、現在実行中のdelayed_work
関数が終了し、最後のものと同じCPU上のいくつかの時点で実行されますでしょう最初に実行します。これは、delayed_work
またはwork_struct
オブジェクトを再初期化しておらず、work->func
ポインタを変更していないことを前提としています。
ロング回答
したがって、最初のオフ、struct delayed_work
がその最初のメンバーとしてstruct work_struct
を埋め込むことによりstruct work_struct
から導出する疑似継承を使用します。このサブシステムは、いくつかの深刻な並行性を持つために、いくつかの驚くべき原子ビットフリッジングを使用します。 data
フィールドにWORK_STRUCT_PENDING
ビットが設定されている場合、work_struct
は「所有」です。作業者が作業を実行するときには、releases ownershipがあり、最後の作業プールはプライベートset_work_pool_and_clear_pending()関数で記録されます。これはAPIがwork_struct
オブジェクトを最後に変更した時刻です(もちろんスケジュールを変更するまで)。 cancel_delayed_work()
を呼び出すと全く同じことが行われます。
cancel_delayed_work()
を呼び出すと、仕事関数がすでに実行されているときには、まだ実行中であっても誰も所有していないので、false
(広告として)を返します。ただし、schedule_delayed_work()
で再度追加しようとすると、examine the workが最後にpool_workqueue
を見つけて、pool_workqueue
の作業者のいずれかがあなたの作業を現在実行しているかどうかを確認します。それらが(work->func
ポインターを変更していない)場合は、単にpool_workqueue
のキューに作業を追加するだけで、再入場が回避されます。それ以外の場合は、現在のCPUのプールにキューを入れます。 (work->func
ポインタチェックの理由はwork_struct
オブジェクトの再利用を可能にすることである。)
注しかし仕事は、あなたは間違いなく、まだキューに登録され、その場合、単純に最初にそれをキャンセルせずschedule_delayed_work()
を呼び出すとに何変化が生じないということ最初にキャンセルする必要があります。
編集:ああ、もしあなたがDocumentation/workqueue.txt
についての議論で混乱しているなら、無視してください。このフラグは廃止され、無視され、すべてのワークキューは非再入可能になりました。
uugh!これが私の現在のジレンマです。実のところ、私が知っていたバックトレースの1つは、上記の正確なコードを実行した後に再入力した可能性があることを示しています。私はそれを防ぐために原子カウンタを追加しましたが、delayed_workの再スケジュールも正しい方法を知る必要があります。 –