LWNは、RCU で次の例を示します。
RCU で保護された hlist を購読することも、循環リストに似ています。
1 rcu_read_lock(); 2 hlist_for_each_entry_rcu(p, q, head, list) { 3 do_something_with(p->a, p->b, p->c); 4 } 5 rcu_read_unlock();
クイック クイズ 3 : list_for_each_entry_rcu() には 1 つしか必要ないのに、hlist_for_each_entry_rcu() に 2 つのポインターを渡す必要があるのはなぜですか?
回答: hlist では、先頭に遭遇するのではなく、NULL をチェックする必要があるためです。(単一ポインタ hlist_for_each_entry_rcu() をコーディングしてみてください。いい解決策を思いついたら、それはとても良いことです!)
hlist_for_each_entry_rcu() の古いバージョンを参照する必要があると思います。rculist.h
ヘッダーの現在のバージョン (3.13.0) は、実際には 3 つの引数を取る定義を示しているhlist_for_each_entry_rcu
ため、4 番目のポインターを追加する必要がなくなり、それほど難しくないようです。発明:
#define hlist_for_each_entry_rcu(pos, head, member) \
for (pos = hlist_entry_safe (rcu_dereference_raw(hlist_first_rcu(head)),\
typeof(*(pos)), member); \
pos; \
pos = hlist_entry_safe(rcu_dereference_raw(hlist_next_rcu(\
&(pos)->member)), typeof(*(pos)), member))
現在の rculist.h で指定されている何かまたはそれ以上のバージョンが欠けているのでしょうか?
__rcu_dereference_check
追加のポインターが作成される場所で、微妙なことが起こっていることがわかります。
#define rcu_dereference_raw(p) rcu_dereference_check(p, 1) /*@@@ needed? @@@*/
#define rcu_dereference_check(p, c) \
__rcu_dereference_check((p), rcu_read_lock_held() || (c), __rcu)
#define __rcu_dereference_check(p, c, space) \
({ \
typeof(*p) *_________p1 = (typeof(*p)*__force )ACCESS_ONCE(p); \
rcu_lockdep_assert(c, "suspicious rcu_dereference_check()" \
" usage"); \
rcu_dereference_sparse(p, space); \
smp_read_barrier_depends(); \
((typeof(*p) __force __kernel *)(_________p1)); \