在引入RCU锁的article中,他编写了一个发布 - 订阅机制。但我有一个关于 rcu_assign_pointer()的问题,在这篇文章中,他说:
1 p->a = 1;
2 p->b = 2;
3 p->c = 3;
4 rcu_assign_pointer(gp, p);
rcu_assign_pointer()将发布新结构,强制两者 编译器和CPU执行后分配给gp 对p。
引用的字段的赋值
但编译器和CPU怎么知道 p 已被分配?例如,如果我只是初始化p-> a和p-> b,那么编译器和CPU如何区分这两者情况?
situation 1:
1 p->a = 1;
2 p->b = 2;
3 p->c = 3;
4 rcu_assign_pointer(gp, p);
situation 2:
1 p->a = 1;
2 p->b = 2;
3 rcu_assign_pointer(gp, p);
对于读取侧的关键部分,如果有连续读者读取数据,编写者是否必须等待它们或者编写者不能进行同步操作?如果是,读者将始终阅读旧版本?
答案 0 :(得分:0)
对问题1的回答: rcu_assign_pointer()指示编译器不要优化机器指令,以便对“' p”字段进行任何修改。在rcu_assign_pointer()语句之前完成,在实现/代码中,在分配' p'之前在CPU管道中执行。到了#gp'。这确保了当' gp'获得分配后,开发人员选择进行分配的所有字段' p'以及现在' gp'确实已分配。
为了进一步说明,请使用以下代码,其目的是返回' y'回到来电者:
void
my_func(struct foo **y)
{
struct foo *x = malloc(sizeof (struct foo));
x->val1 = 1;
*y = x;
x->val2 = 2;
return;
}
开发人员并不真正关心上面的赋值语句的顺序,因为他/她的意图是简单地返回* y填充2个值。因此,给定如上所述的代码,编译器可以选择在CPU管道中并行执行3个赋值语句,并且它不会破坏正确性。
现在,如果在执行rcu类型的工作时使用类似的赋值语句,编译器可能会选择执行相同类型的优化,因此读者可能最终会使用"部分初始化" ' GP&#39 ;. rcu_assign_pointer()确保保持分配顺序,以便开发人员的意图,即分配' p'到' gp'在所有p字段初始化之后,保留。
这有希望说明,如果您,开发人员在分配' p'之前选择仅分配p-> a和p-> b,而不指定p-> c。到了gp',那就是gp会得到什么 - 一个部分初始化的结构。
回答问题2: