1

Question 1:

In the article to introduce RCU lock, he writes a publish-subscribe mechanism. But I have a question about rcu_assign_pointer(), in this article, he said:

1 p->a = 1;
2 p->b = 2;
3 p->c = 3;
4 rcu_assign_pointer(gp, p);

The rcu_assign_pointer() would publish the new structure, forcing both the compiler and the CPU to execute the assignment to gp after the assignments to the fields referenced by p.

But how could compiler and CPU know p has been assigned?For example, If I just initialise the p->a and p->b, then how compiler and CPU distinguish the two situation?

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);

Question 2:

As for the read-side critical section, If there are continuous readers to read the data, should writer must wait for them or writer couldn't do the synchronise operation? If yes, reader will always read the older version?

yifan_z
  • 256
  • 1
  • 10

1 Answers1

0

Answer to Question1: rcu_assign_pointer() instructs the compiler not to optimize the machine-instructions, such that any modifications to fields of 'p' done before the rcu_assign_pointer() statement, in the implementation/code, are executed in the CPU-pipeline before the assignment of 'p' to 'gp'. This makes sure that when 'gp' gets assigned, all the fields of 'p', and hence now 'gp', that the developer chose to assign are indeed assigned.

To illustrate further, take the following code, whose intent is to return 'y' back to the caller:

void my_func(struct foo **y) { struct foo *x = malloc(sizeof (struct foo)); x->val1 = 1; *y = x; x->val2 = 2; return; }

The developer does not really care about the order of the assignment statements above because his/her intent is to simply return *y filled with 2 values. Hence, given code like the above, the compiler can choose to execute the 3 assignment statements in parallel in the CPU-pipelines and it does not break correctness.

Now, if you use a similar assignment statement when doing rcu type of work, the compiler might choose to do the same kind of optimization and hence readers might end up with a "partially-initialized" 'gp'. rcu_assign_pointer() makes sure the ordering of assignment is maintained so that the developer's intent, to assign 'p' to 'gp' AFTER all of p's fields have been initialized, is preserved.

This hopefully should illustrate that if you, the developer, chose to assign only p->a and p->b, without assigning p->c, before assigning 'p' to 'gp', then that's what gp will get - a partially-initialized structure.

Answer to Question2:

Anand Ganesh
  • 331
  • 2
  • 6