RCUインタフェースの例
出典: フリー百科事典『ウィキペディア(Wikipedia)』 (2019/01/13 15:24 UTC 版)
「リード・コピー・アップデート」の記事における「RCUインタフェースの例」の解説
RCUはいくつかのOSで利用可能であり、Linuxカーネルには2002年10月に追加された。liburcu などのユーザーレベルの実装も利用可能である。 Linuxカーネル 2.6 でのRCU実装はよく知られており、以下ではそれを元に RCU API について解説する。中核となるAPIは極めて小さい。 rcu_read_lock(): RCUで保護されたデータへの参照を開始することを示す。それによってクリティカルセクション期間中に対象データが再利用されないようにする。 rcu_read_unlock(): 参照者が使用し、参照者が参照側クリティカルセクションから出たことを更新者に通知する。RCUの参照側クリティカルセクションはネスト可能であり、オーバーラップ可能である。 synchronize_rcu(): 全CPU上の既存のRCU参照側クリティカルセクションが全て完了するまでブロックされる。synchronize_rcu は後続のRCU参照側クリティカルセクションを待つ必要はない。たとえば、以下のようなイベントの流れを考えてみよう。 CPU 0 CPU 1 CPU 2 ----------------- ------------------------- --------------- 1. rcu_read_lock() 2. enters synchronize_rcu() 3. rcu_read_lock() 4. rcu_read_unlock() 5. exits synchronize_rcu() 6. rcu_read_unlock() synchronize_rcu は参照者が参照を完了したことを判定するAPIであり、RCU実装の要である。RCUは特に参照が多く更新が滅多にない場合に有効であり、synchronize_rcu のオーバーヘッドは極めて小さくなければならない。 ブロックする代わりに synchronize_rcu でコールバック関数と引数を登録し、動作中のRCU参照側クリティカルセクションが完了したときにそれがコールされるようにする実装もある。Linuxカーネルでは、このコールバック型のAPIを call_rcu と呼ぶ。 rcu_assign_pointer(): 更新者が使用し、更新者から参照者に安全に変化を伝え、RCUに保護されたポインタを更新する。この関数は、CPUアーキテクチャ上必要なメモリバリア命令を実行し、新たな値を返す。もっと重要な点として、この関数はどのポインタがRCUによって保護されているかを保証する。 rcu_dereference_pointer(): RCUに保護されたポインタをフェッチするために参照者が使用し、そのポインタが指している値を安全に得る。また、CPUアーキテクチャ上必要なメモリバリア命令も実行する。rcu_dereference_pointer が返す値はRCU参照側クリティカルセクション内でのみ有効である。rcu_assign_pointer との関連で rcu_dereference_pointer の重要な機能は、どのポインタがRCUで保護されているかを示すことである。 以下の図は各APIが参照者、更新者、再利用者の間でどう関係しているかを示している。 rcu_assign_pointer() +--------+ +---------------------->| 参照者 |---------+ | +--------+ | | | | | | | 保護: | | | rcu_read_lock() | | | rcu_read_unlock() | rcu_dereference() | | +---------+ | | | 更新者 |<---------------------+ | +---------+ V | +-----------+ +----------------------------------->| 再利用者 | +-----------+ 遅延: synchronize_rcu() & call_rcu() RCUの内部機構は rcu_read_lock, rcu_read_unlock, synchronize_rcu, call_rcu が呼び出された順番を記憶し、(1) synchronize_rcu がそれらの呼び出し側への戻りを設定するか、(2) call_rcu のコールバックが呼び出される順番を決定する。効果的な実装としては、各APIのオーバヘッドを減らして、背後でバッチ的に処理するほうがよい。
※この「RCUインタフェースの例」の解説は、「リード・コピー・アップデート」の解説の一部です。
「RCUインタフェースの例」を含む「リード・コピー・アップデート」の記事については、「リード・コピー・アップデート」の概要を参照ください。
- RCUインタフェースの例のページへのリンク