Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
RCU資料
Search
Yasuhiro Ohara
December 28, 2024
Programming
230
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
RCU資料
Yasuhiro Ohara
December 28, 2024
More Decks by Yasuhiro Ohara
See All by Yasuhiro Ohara
SRv6-mobile VPP plugin Performance Optimization
yasuhironet
2
730
sdplane wiretap 製品紹介
yasuhironet
0
52
Other Decks in Programming
See All in Programming
WebMCP Challenge に星空観察アプリで参加した話
okajun35
0
190
マイコン向けの軽量Ruby「PicoRuby」で各種デバイスを制御するネイティブアプリの実現手法
bash0c7
0
430
AWS Step Functions 大規模並列の壁を越える / jaws-sonic-2026-niigata-step-functions
kasacchiful
PRO
1
500
Verilogで学ぶCPU自作入門.pdf
uyuki234
1
370
ゲームコントローラやキーボードのファームウェアをSwiftで書く
kishikawakatsumi
1
250
Intent as Code
shoppingjaws
6
1.1k
App Storeの外へ──日本のiOSサイドローディング入門 for iOSDC Japan 2026
yuukiw00w
0
230
『寄り添うラジオ』をAIで作る 体験価値から逆算した、会話しないUXと品質設計
theoriatec2024
3
180
AI が書く Go コードの品質を劇的に向上させる Linter: “declscope”
mpyw
0
380
Snowflakeで業務アプリを作ろう。 Snowflakeのアプリ機能解説&実践ガイド
ayumu_yamaguchi
2
290
[GoCon2026] When Goroutines Are Not Enough: Runtime Locality in High-Throughput Go
takehaya
6
2.4k
WebAssembly in Android Apps 〜 WASMはJNIの夢を見るか
keiji
1
110
Featured
See All Featured
How to build an LLM SEO readiness audit: a practical framework
nmsamuel
1
910
Prompt Engineering for Job Search
mfonobong
0
460
Ecommerce SEO: The Keys for Success Now & Beyond - #SERPConf2024
aleyda
1
2.2k
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
2
2.9k
Testing 201, or: Great Expectations
jmmastey
46
8.3k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
133
19k
How to Talk to Developers About Accessibility
jct
2
550
Lightning Talk: Beautiful Slides for Beginners
inesmontani
PRO
2
700
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
830
How To Speak Unicorn (iThemes Webinar)
marktimemedia
1
580
Claude Code どこまでも/ Claude Code Everywhere
nwiizo
67
58k
Measuring Dark Social's Impact On Conversion and Attribution
stephenakadiri
2
280
Transcript
RCU: Read-Copy-Update • マルチスレッドにおけるリーダーライターロックの代わり。 ロックレス • 参照するデータを変更の世代分⽤意して、すげ替える • 参照スレッド側で(スレッドローカル︖)コピーを持ってそれを読む から、Read-Copy
という名か︖すげ替える部分が Update︖ • QSBR がすごい • RCUには他にも memory barrier とか種類がある • QSBR: Quiescent State Based Reclamation • 多数の参照スレッド、少数(たぶん単⼀を想定)の更新スレッド • 参照スレッド側のオーバヘッドがほぼ皆無︕ • 本資料は QSBR に特化
RCU利⽤例︓⾼速DPDKルータ • RCU︓ロックを回避し、⾼速な同期処理する重要な技術 • DPDK pthreadがコアごとに独⽴して⾼速パケット処理、その間を RCU で調停 • RCUで共有するデータ︓経路表、ポート設定、ACLフィルター設定
DPDK P1 P4 P2 P3 CPU core1 CPU core2 CPU core3 CPU core4 OS l2fwd Forwarder P1/P2 l3fwd Forwarder P3/P4 lthread_main RCU • lthread_main: • startup_config • console_shell • tap_handler • stat_collector • l2fwd • (l3fwd-lpm)
操作関数 • rcu_assign_pointer()︓ • ポインタ登録。更新スレッドが使⽤。 • rcu_dereference()︓ • ポインタ取得。参照スレッドが毎回の read
critical section の先頭で使⽤。 • urcu_qsbr_quiescent_state()︓ • read critical section 外で、read critical section 外だということを、報告 する関数。参照スレッドが使⽤。 • urcu_qsbr_synchronize_rcu()︓ • 前スレッドが read critical section を⼀回以上抜けるまで待つ。更新スレッ ドが使⽤。この関数を呼び出し、帰って来れば、古い共有データのポインタ を保持している参照スレッドは居ないことが保証される。 • urcu_qsbr_register_thread()︓参照スレッド登録。 • urcu_qsbr_unregister_thread()︓参照スレッド登録の解除。
rcu-qsbr 更新スレッド 時間 データ 参照スレッド 参照スレッドのループの ⼀繰り返し期間は、 スレッド間でも、 スレッド内でも、 ⼀定ではない
参照スレッド 参照スレッド ループ quiescent_state() rcu_assign_pointer() read critical section synchronize_rcu() reclamation: 回収、再利⽤(削除) ⾚か⻘か不明な read critical section ⾚を保持する参照スレッドは居ない (だから消せる) read critical sectionは 毎回 rcu_dereference() し直して最新のポインタ取得 データ更新
Userscace RCU 実装内部 • カウンタを使ってスレッド間の緩い同期を図る • カウンタなのでほぼオーバヘッド無し • rcu_gp_ctr 変数(unsigned
long)。rcu_global_pointer_counter の略か。 • TLS(Thread-Local Storage)を使⽤。 • futex というカーネルサービスを使ってスレッドの WAKE/WAIT を実現 している • つまり、完全にユーザスペースで動くわけではなく、カーネル futex サービスを利 ⽤してユーザスペースでも機能する RCU ライブラリ、という位置付け。 • quiescent_state()︓ • rcu_gp_ctr を⾃スレッドローカルで更新し、そのカウンタ(カウント数)で待って るスレッドを futex で wakeup。 • rcu_synchronize()︓ • futex で全スレッドを待つ。
urcu-qsbr 使い⽅(更新スレッド) void *rcu_global_ptr_rib; void rib_replace () { #if HAVE_LIBURCU_QSBR
struct rib *new, *old; /* allocate new */ new = malloc (sizeof (struct rib)); /* retrieve old */ old = rcu_dereference (rcu_global_ptr_rib); if (old) memcpy (new, old, sizeof (struct rib)); /* update new */ rib_edit (new) ... /* assign new */ rcu_assign_pointer (rcu_global_ptr_rib, new); /* wait all readers to update. */ urcu_qsbr_synchronize_rcu (); /* reclaim old */ free (old); #endif /*HAVE_LIBURCU_QSBR*/ }
urcu-qsbr 使い⽅(参照スレッド)(1) #if HAVE_LIBURCU_QSBR urcu_qsbr_register_thread (); #endif /*HAVE_LIBURCU_QSBR*/ /* main
loop */ while (! force_quit && ! force_stop[lcore_id]) { #if HAVE_LIBURCU_QSBR urcu_qsbr_read_lock (); rib = (struct rib *) rcu_dereference (rcu_global_ptr_rib); #endif /*HAVE_LIBURCU_QSBR*/ パケット受信(); パケット処理(); #if HAVE_LIBURCU_QSBR urcu_qsbr_read_unlock (); urcu_qsbr_quiescent_state (); #endif /*HAVE_LIBURCU_QSBR*/ loop_counter++; } #if HAVE_LIBURCU_QSBR urcu_qsbr_unregister_thread (); #endif /*HAVE_LIBURCU_QSBR*/ } read critical section
urcu-qsbr 使い⽅(参照スレッド)(2) #if HAVE_LIBURCU_QSBR urcu_qsbr_register_thread (); #endif /*HAVE_LIBURCU_QSBR*/ /* main
loop */ while (! force_quit && ! force_stop[lcore_id]) { #if HAVE_LIBURCU_QSBR urcu_qsbr_read_lock (); rib = (struct rib *) rcu_dereference (rcu_global_ptr_rib); #endif /*HAVE_LIBURCU_QSBR*/ パケット受信(); パケット処理(); #if HAVE_LIBURCU_QSBR urcu_qsbr_read_unlock (); urcu_qsbr_quiescent_state (); #endif /*HAVE_LIBURCU_QSBR*/ loop_counter++; } #if HAVE_LIBURCU_QSBR urcu_qsbr_unregister_thread (); #endif /*HAVE_LIBURCU_QSBR*/ } read critical section read_lock(), read_unlock()は qsbr の場合は本当に何もしない、 呼ばなくても良い
urcu-qsbr 使い⽅(参照スレッド)(3) #if HAVE_LIBURCU_QSBR urcu_qsbr_register_thread (); #endif /*HAVE_LIBURCU_QSBR*/ /* main
loop */ while (! force_quit && ! force_stop[lcore_id]) { #if HAVE_LIBURCU_QSBR rib = (struct rib *) rcu_dereference (rcu_global_ptr_rib); #endif /*HAVE_LIBURCU_QSBR*/ パケット受信(); パケット処理(); #if HAVE_LIBURCU_QSBR urcu_qsbr_quiescent_state (); #endif /*HAVE_LIBURCU_QSBR*/ loop_counter++; } #if HAVE_LIBURCU_QSBR urcu_qsbr_unregister_thread (); #endif /*HAVE_LIBURCU_QSBR*/ } read critical section read_lock(), read_unlock()は qsbr の場合は本当に何もしない、 呼ばなくても良い
urcu-qsbr 使い⽅(まとめ) 更新スレッド︓ void *var; writer(){ void *old, *new; new
= create_new (); rcu_assign_pointer (var, new); synchronize_rcu (); free (old); } 参照スレッド︓ reader() { urcu_qsbr_register_thread (); while(1) { rcu_quiescent_state (); //rcu_read_lock(); p = rcu_dereference (var); ... //critical section using p. //rcu_read_unlock(); } urcu_qsbr_unregister_thread (); }
注意点︓ • 利⽤ユーザ側が⾃分で守らなければいけないルール︓ • read critical section の外から、中に⼊った時には、 rcu_dereference() し
て最新のポインタを取得することがルール。 • quiescent_state() の前後で、同じ古いポインタを維持・参照しないこと。 rcu_dereference() し直すこと。 • 参照スレッドは全て登録(register_thread())すること。 • ⾃由度︓ • ⼀ループ繰り返しの中では、read critical section の外であれば、 quiescent_state() は前でも後ろでも良い。呼び出し(報告)場所はどこで も⼤丈夫。(毎回rcu_dereference()していれば、)read critical section が細切れにたくさんあって、その途中のどこかでも⼤丈夫。複数回呼んでも ⼤丈夫。 • 更新スレッド⾃⾝を参照スレッド登録するのはちょっと複雑で危険。 デッドロックっぽいスレッド停⽌が起きた。
ポート設定コンフリクト • ポート設定をrcu変更すると き、スレッド間でタイミング 合わない(同期しない)と、 同じポート(queue)にアク セスして、クラッシュする t1 t2 p0
p1 thread: t1 port: 0 thread: t2 port: 1 thread: t1 port: 0 thread: t1 port: 1 rcu x
ポート設定コンフリクトの解消 • rcuで、コンフリクトが解消 できるような中間状態の設定 を追加することで、スレッド 間の同期も実現できる • (差分計算が⾯倒くさければ、 緑の中間状態を空にしてしま えば、効率性・性能を犠牲に
して安全性を獲得できる) t1 t2 p0 p1 thread: t1 port: 0 thread: t2 port: 1 thread: t1 port: 0 rcu t1 t2 p0 p1 thread: t1 port: 0 thread: t1 port: 0 thread: t1 port: 1 rcu