1,RCU(Read-Copy
Update),顾名思义就是读-拷贝修改,它是基于其原理命名的。对于被RCU保护的共享数据结构,读者不需要获得任何锁就可以访问它,但写者在访问它
时首先拷贝一个副本,然后对副本进行修改,最后使用一个回调(callback)机制在适当的时机把指向原来数据的指针重新指向新的被修改的数据。这个时
机就是所有引用该数据的CPU都退出对共享数据的操作
2,RCU 核心API
---------------------------|rcu_read_lock|------------------------------------
#define rcu_read_lock() __rcu_read_lock()
读者在读取由RCU保护的共享数据时使用该函数标记它进入读端临界区
---------------------------|rcu_read_unlock|------------------------------------
#define rcu_read_unlock() __rcu_read_unlock()
该函数与rcu_read_lock配对使用,用以标记读者退出读端临界区
---------------------------|synchronize_rcu|------------------------------------
void synchronize_rcu(void)
该函数由RCU写端调用,它将阻塞写者,直到经过grace period后,即所有的读者已经完成读端临界区,写者才可以继续下一步操作.一般在彻底退出的时候使用
---------------------------|rcu_dereference|------------------------------------
#define rcu_dereference(p) ({ typeof(p) _________p1 = ACCESS_ON
CE(p);
smp_read_barrier_depends(); (_________p1); })
该宏用于在RCU读端临界区获得一个RCU保护的指针,该指针可以在以后安全地引用
---------------------------|rcu_assign_pointer|------------------------------------
#define rcu_assign_pointer(p, v) ({ if (!__builtin_constant_p(v) || ((v) != NULL))
smp_wmb(); (p) = (v); })
写者使用该函数来为被RCU保护的指针分配一个新的值.这样是为了安全从写者到读者更改其值.这个函数会返回一个新值
---------------------------||------------------------------------
void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu))
该函数将把函数 func 挂接到 RCU回调函数链上,然后立即返回,由 RCU 写端调用
---------------------------||------------------------------------
void call_rcu_bh(struct rcu_head *head, void (*func)(struct rcu_head *rcu))
函数call_ruc_bh功能几乎与call_rcu完全相同,唯一差别就是它把softirq的完成也当作经历一个quiescent state,因此如果写端使用了该函数,在进程上下文的读端必须使用rcu_read_lock_bh。
---------------------------||------------------------------------
static inline void list_add_rcu(struct list_head *new, struct list_head *head)
函数把链表项new插入到RCU保护的链表head的开头
---------------------------||------------------------------------
static inline void list_add_tail_rcu(struct list_head *new, struct list_head *head)
把新的链表项new添加到被RCU保护的链表的末尾
---------------------------||------------------------------------
static inline void list_del_rcu(struct list_head *entry)
函数从RCU保护的链表中移走指定的链表项entry,并且把entry的prev指针设置为LIST_POISON2,但是并没有把entry的next指针设置为LIST_POISON1,因为该指针可能仍然在被读者用于便利该链表。
---------------------------||------------------------------------
static inline void list_replace_rcu(struct list_head *old, struct list_head *new)
该函数是RCU新添加的函数,并不存在非RCU版本。它使用新的链表项new取代旧的链表项old,内存栅保证在引用新的链表项之前,它的链接指针的修正对所有读者可见
阅读(781) | 评论(0) | 转发(1) |