RCU锁中的发布-订阅机制和读侧临界区

  • 本文关键字:机制 临界区 RCU rcu
  • 更新时间 :
  • 英文 :


问题1:

在介绍RCU锁的文章中,他写了一个publish-subscribe机制。但是我对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);

问题2:

对于读侧临界区,如果有连续的读端在读数据,写端是必须等待还是不能进行同步操作?如果是,读者会一直读旧版本吗?

问题1的答案:rcu_assign_pointer()指示编译器不要优化机器指令,这样在rcu_assign_pointer()语句之前对'p'字段的任何修改,在实现/代码中,在'p'赋值给'gp'之前,在cpu管道中执行。这确保当'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。因此,对于像上面这样的代码,编译器可以选择在cpu管道中并行执行3个赋值语句,这不会破坏正确性。

现在,如果你在做rcu类型的工作时使用类似的赋值语句,编译器可能会选择做同样的优化,因此读者可能最终得到一个"部分初始化"的"gp"。rcu_assign_pointer()确保了赋值的顺序被维护,这样开发人员的意图,即在p的所有字段初始化之后,将'p'赋值给'gp'。

希望这能说明,如果你,开发人员,选择只赋值p->a和p->b,而不赋值p->c,在将'p'赋值给'gp'之前,gp将得到-一个部分初始化的结构。

问题2的答案:

相关内容

  • 没有找到相关文章

最新更新