???????
????RCU??Read-Copy Update??????????????????????????Linux????з?????????????á?RCU????????????????????????????????????????Ч?????????????RCU??????????????????????к????????????????????????????ж?????????????????????????????????????????????????????????????RCU???????????????????????????????????????????????????????У?????????????λ???????????????????????????????RCU???????????????
????Linux???????У?????RCU???????????????????? /Documentation/RCU/ ?????????Щ?????Paul E. McKenney ???????RCU????????????????д????RCU????????????????Щ???o??Щ????RCU?????????????????????
??????RCU?????????У???????????????????
????1???????????У????????????????????????????????????????????????????????????????????????????????е????????????????????????????RCU?а?????????????????Grace period????
????2???????????У????????????????????????????????????????????????????????????????????????????漰???????-????????Publish-Subscribe Mechanism????
????3?? ???????????????????????????????????????????±????????????м?????????RCU?????????????????????????????????????????
??????????
????????????????????????????????????????Paul???????
struct foo {
int a;
char b;
long c;
};
DEFINE_SPINLOCK(foo_mutex);
struct foo *gbl_foo;
void foo_read (void)
{
foo *fp = gbl_foo;
if ( fp != NULL )
dosomething(fp->a?? fp->b ?? fp->c );
}
void foo_update( foo* new_fp )
{
spin_lock(&foo_mutex);
foo *old_fp = gbl_foo;
gbl_foo = new_fp;
spin_unlock(&foo_mutex);
kfee(old_fp);
}
struct foo {
int a;
char b;
long c;
};
DEFINE_SPINLOCK(foo_mutex);
struct foo *gbl_foo;
void foo_read (void)
{
foo *fp = gbl_foo;
if ( fp != NULL )
dosomething(fp->a?? fp->b ?? fp->c );
}
void foo_update( foo* new_fp )
{
spin_lock(&foo_mutex);
foo *old_fp = gbl_foo;
gbl_foo = new_fp;
spin_unlock(&foo_mutex);
kfee(old_fp);
}
?????????????????????????gbl_foo??????????????3???????????????????? foo_ read??foo_update???????foo_ read???????????????????л???????????????????foo_update???????ɡ???foo_ read???е?????л???????????dosomething ?????fp???????????????????Σ???????????????????????RCU????????????μ????п??????Grace period??????????????

?????????д??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Щ????п????????????????????е???????????1??2?????????????5???????????????????????????????3??4??6???????????????????????????????????????????????????????RCU?????????????API?????????????
void foo_read(void)
{
rcu_read_lock();
foo *fp = gbl_foo;
if ( fp != NULL )
dosomething(fp->a??fp->b??fp->c);
rcu_read_unlock();
}
void foo_update( foo* new_fp )
{
spin_lock(&foo_mutex);
foo *old_fp = gbl_foo;
gbl_foo = new_fp;
spin_unlock(&foo_mutex);
synchronize_rcu();
kfee(old_fp);
}
void foo_read(void)
{
rcu_read_lock();
foo *fp = gbl_foo;
if ( fp != NULL )
dosomething(fp->a??fp->b??fp->c);
rcu_read_unlock();
}
void foo_update( foo* new_fp )
{
spin_lock(&foo_mutex);
foo *old_fp = gbl_foo;
gbl_foo = new_fp;
spin_unlock(&foo_mutex);
synchronize_rcu();
kfee(old_fp);
}
????????foo_read????????rcu_read_lock??rcu_read_unlock??????????????????????RCU????????????????????????????????????????????foo_update?????????????synchronize_rcu()??????ú?????ζ?????????????????????????????????ú??????????????????????????????1??2????synchronize_rcu????????????gbl_foo?????foo_update?е?old_fp????????????????н?????????kfee(old_fp)?????п????????????????3??4??6??synchronize_rcu??????У???????????????????old_fp????ε?kfee????????????????
????????????RCU????и???????????????????????????????????????????????????
????????——????????
??????????????????????????????????????CPU?????????????Щ????????????????????????Ч???????????????????????????????????????????
void foo_update( foo* new_fp )
{
spin_lock(&foo_mutex);
foo *old_fp = gbl_foo;
new_fp->a = 1;
new_fp->b = ‘b’;
new_fp->c = 100;
gbl_foo = new_fp;
spin_unlock(&foo_mutex);
synchronize_rcu();
kfee(old_fp);
}
void foo_update( foo* new_fp )
{
spin_lock(&foo_mutex);
foo *old_fp = gbl_foo;
new_fp->a = 1;
new_fp->b = ‘b’;
new_fp->c = 100;
gbl_foo = new_fp;
spin_unlock(&foo_mutex);
synchronize_rcu();
kfee(old_fp);
}
??????δ????У?????????????6??7??8?е???????10?д???????С??????????????????????????????????????????£???????????????? new_fp????new_fp???????????????ɡ???????????dosomething(fp->a?? fp->b ?? fp->c ) ?? ????в?????????????dosomething?????п???????????????????????????????????????????????????????RCU????????????????????????????API????????????????????в?????????????????????? :
#define rcu_assign_pointer(p?? v)
__rcu_assign_pointer((p)?? (v)?? __rcu)
#define __rcu_assign_pointer(p?? v?? space)
do {
smp_wmb();
(p) = (typeof(*v) __force space *)(v);
} while (0)
#define rcu_assign_pointer(p?? v)
__rcu_assign_pointer((p)?? (v)?? __rcu)
#define __rcu_assign_pointer(p?? v?? space)
do {
smp_wmb();
(p) = (typeof(*v) __force space *)(v);
} while (0)
????????????????????????????????????????? smp_wmb??????????????????????????????__rcu?????????????????????????????
??????DEC Alpha CPU????????????????????????????????
void foo_read(void)
{
rcu_read_lock();
foo *fp = gbl_foo;
if ( fp != NULL )
dosomething(fp->a?? fp->b ??fp->c);
rcu_read_unlock();
}
void foo_read(void)
{
rcu_read_lock();
foo *fp = gbl_foo;
if ( fp != NULL )
dosomething(fp->a?? fp->b ??fp->c);
rcu_read_unlock();
}
?????????е? fp->a??fp->b??fp->c?????3?л????е????????ж????У???????foo_update?????е??????????′???dosomething?????????????gbl_foo??????????????μ?????????????н????????????????????RCU????????????????????
#define rcu_dereference(p) rcu_dereference_check(p?? 0)
#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));
})
static inline int rcu_read_lock_held(void)
{
if (!debug_lockdep_rcu_enabled())
return 1;
if (rcu_is_cpu_idle())
return 0;
if (!rcu_lockdep_current_cpu_online())
return 0;
return lock_is_held(&rcu_lock_map);
}
#define rcu_dereference(p) rcu_dereference_check(p?? 0)
#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));
})
static inline int rcu_read_lock_held(void)
{
if (!debug_lockdep_rcu_enabled())
return 1;
if (rcu_is_cpu_idle())
return 0;
if (!rcu_lockdep_current_cpu_online())
return 0;
return lock_is_held(&rcu_lock_map);
}