4

( LWNの記事より)

 1 rcu_read_lock();
 2 list_for_each_entry_rcu(p, head, list) {
 3   do_something_with(p->a, p->b, p->c);
 4 }
 5 rcu_read_unlock();

RCU 更新操作は、各 CPU がコンテキストを切り替えたことをアサートするために synchronize_rcu() を実行するため、各 RCU リーダーはそのジョブを完了しました。しかし、RCU はリーダーが横取りされないことに依存しなければなりません。実際、LWN は次のように述べています。

この単純なアプローチは、RCU 読み取り側クリティカル セクション全体でプリエンプションが無効になっているカーネル、つまり、CONFIG_PREEMPT および CONFIG_PREEMPT 以外のカーネルでは機能しますが、CONFIG_PREEMPT_RT リアルタイム (-rt) カーネルでは機能しません。

非 CONFIG_PREEMPT カーネルではプリエンプションが無効になっていることは理解していますが、なぜCONFIG_PREEMPTカーネルでも問題ないのでしょうか?

4

2 に答える 2

5

CONFIG_PREEMPT カーネルでは、タスクがプリエンプトされる前に rcu read クリティカル セクションを終了するように注意が払われるため、問題ありません。スケジューラは、現在のタスクが rcu 読み取りクリティカル セクションにあるかどうかを確認し、そうであれば、クリティカル セクションを終了するように優先度を上げます。詳細については、この記事を参照してください: http://lwn.net/Articles/220677/

于 2015-08-28T17:40:41.997 に答える
1

CONFIG_PREEMPT カーネルには RCU が必要です。プリエンプションやブロッキングがなければ、この同期の混乱はありません。RCU 実装には 2 つのタイプがあります。

1) Non-preemptible RCU implementation
2) Preemptible RCU implementation

ある CPU で synchronize_rcu() が呼び出され、他の CPU が RCU 読み取り側クリティカル セクション内にある場合、synchronize_rcu() は、他のすべての CPU がクリティカル セクションを終了するまでブロックすることが保証されます。同様に、ある CPU で call_rcu() が呼び出され、他の CPU が RCU 読み取り側クリティカル セクション内にある場合、対応する RCU コールバックの呼び出しは、他のすべての CPU がクリティカル セクションを終了するまで延期されます。

プリエンプティブルでない RCU 実装では、RCU 読み取り側のクリティカル セクションにいる間にブロックすることは違法です。CONFIG_PREEMPT カーネル ビルドのプリエンプティブル RCU 実装 (PREEMPT_RCU) では、RCU 読み取り側クリティカル セクションがプリエンプトされる可能性がありますが、明示的なブロックは違法です。最後に、リアルタイム (-rt パッチセットを使用) カーネル ビルドでのプリエンプティブル RCU 実装では、RCU 読み取り側クリティカル セクションがプリエンプトされる可能性があり、それらもブロックされる可能性がありますが、優先度継承の対象となるスピンロックを取得する場合のみです。

于 2015-08-28T09:22:39.007 に答える