Again, suppose a Linux-kernel task registers a pair of RCU callbacks, as follows:
call_rcu(&p->rcu, myfunc); smp_mb(); call_rcu(&q->rcu, myfunc);
Given that these two callbacks are guaranteed to be registered in order, are they also guaranteed to be invoked in order?
Unfortunately, the answer is “no”. Here is one sequence of events that can result in misordering:
Thus, the callbacks are invoked out of order.
Please note that this is but one misordering scenario. There are many other ways that callbacks can be misordered, for example, courtesy of the fact that different CPUs become aware of the beginning and end of a given grace period at different times.
Of course, those familiar with the Linux-kernel RCU implementation will be quick to point out that it does provide an ordering guarantee if preemption is disabled:
preempt_disable(); call_rcu(&p->rcu, myfunc); smp_mb(); call_rcu(&q->rcu, myfunc); preempt_enable();
However, this is a consequence of the current implementation of rcu_barrier() rather than a hard-and-fast property of RCU in general. And this implementation may have to change, for example, if systems continue to increase in size and workloads continue to increase in variety, it might become necessary to load-balance RCU callbacks. This change would of course mean that callbacks could be misordered even if they were registered from a single task with preemption disabled. This would in turn require rcu_barrier() to be redesigned, but redesign appears to be par for the course for the Linux-kernel RCU implementation!
So what if your code needs RCU callbacks to be invoked in order? Here are some ways of making that happen:
Given that the common case is for RCU callbacks to simply free memory, ordering should be the exception rather than the rule.