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
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
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
750
sdplane wiretap 製品紹介
yasuhironet
0
59
Other Decks in Programming
See All in Programming
Starting & Sustaining Code-Based E2E Testing for Non-Coding QA Teams( #jasstniigata )
teyamagu
PRO
1
1k
PumaからFalconに移行したRailsアプリケーションでの実践
falcon8823
0
170
気持ちぃ〜角丸 Squircle
ryu1013
0
310
最近”作らせてる” ローカルAIアプリの話
akit37
0
470
Agents on Rails - Rails at Scale 2026
irinanazarova
0
560
全ての永続トークンを、生まれる前に消し去りたい!
sylph01
2
880
作れる、でも消せるか?──安全に「枯らして消す」機能削除術 / Drain, Then Delete
chobishiba
2
640
ハーネス設計入門 〜 基礎知識の整理から実務へのステップアップ 〜
kinopeee
28
32k
なぜCTOを降りてFDEを選んだのか?〜なぜプロダクト企業がFDEで顧客の現場に踏み込むのか〜
gonta
1
210
Event is what happens
moro
2
770
Herb in Rails 8.2: Your ERB views, now HTML-aware @ Kaigi on Rails 2026, Tokyo, Japan
marcoroth
2
220
sbt 2.0: takeoff
eed3si9n
0
160
Featured
See All Featured
Documentation Writing (for coders)
carmenintech
77
5.6k
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
Fashionably flexible responsive web design (full day workshop)
malarkey
409
67k
Game over? The fight for quality and originality in the time of robots
wayneb77
1
300
Code Review Best Practice
trishagee
74
20k
Heart Work Chapter 1 - Part 1
lfama
PRO
10
37k
A better future with KSS
kneath
240
18k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
12
1.3k
We Analyzed 250 Million AI Search Results: Here's What I Found
joshbly
2
2k
Automating Front-end Workflow
addyosmani
1369
210k
WENDY [Excerpt]
tessaabrams
14
40k
Building the Perfect Custom Keyboard
takai
2
910
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