On 21 March 2014 14:12, Srivatsa S. Bhat srivatsa.bhat@linux.vnet.ibm.com wrote:
You can find some information on this in Documentation/memory-barriers.txt
Yep, I know, I have read it several times, but I'm no expert ;-)
Not me either :) .. That file has so complex stuff in there that its difficult to understand what's all it says.. I read it several times the last time I went for a interview (Almost 2 years back) and don't remember anything now :)
I found this interesting section on "SLEEP AND WAKE-UP FUNCTIONS". It says that doing:
policy->transition_ongoing = false; wake_up(&policy->transition_wait);
is safe (as long as some tasks are woken up). So we don't have to worry about that part.
Okay..
So only the first part remains to be solved: ensuring that the assignment occurs _after_ completing the invocation of the POSTCHANGE notifiers.
For that, we can do:
cpufreq_notify_post_transition();
smp_mb();
policy->transition_ongoing = false;
That should take care of everything.
I don't think compiler or CPU will reorder calls to a function and updates of a variable.
I'm not sure about that. I think it is free to do so if it finds that there is no dependency that prevents it from reordering. In this case the update to the flag has no "visible" dependency on the call to post_transition().
And so this code might simply work. And I hope there would be plenty of such code in kernel.
Sure, there are plenty of examples in the kernel where we call functions and update variables. But in this particular case, our synchronization _depends_ on those operations happening in a particular order. Hence we need to ensure the ordering is right. Otherwise the synchronization might get broken.
I still don't buy that.. Lets call an expert :)
Here are some examples where memory barriers are inserted to avoid reordering of variable updates and function calls:
kernel/rcu/torture.c: rcu_torture_barrier_cbs()
rcutorture.c instead.
kernel/smp.c: kick_all_cpus_sync()
These examples are a bit different than what we have here..
@Catalin: We have a problem here and need your expert advice. After changing CPU frequency we need to call this code:
cpufreq_notify_post_transition(); policy->transition_ongoing = false;
And the sequence must be like this only. Is this guaranteed without any memory barriers? cpufreq_notify_post_transition() isn't touching transition_ongoing at all..
-- thanks..