On 31 October 2012 23:30, Peter Fordham peter.fordham@gmail.com wrote:
OK so if I understand you correctly your saying that the memory barriers aren't fundamental to the correct operation of this spinlock itself but are required to make all the memory access started inside the critical section actually complete inside the critical section, right?
Partially.
I guess what I'm saying is that isn't it up to the calling code to decide exactly how this should be done rather than the locking code. For example, if I'm just using a spinlock in the place of a mutex in a time critical section of where I want to avoid a call into the scheduler and I'm not really poking registers in a memory mapped device, just updating some shared data structure in normal cache-able memory, it seems inappropriate to use DMBs. I see examples of this in the ext4 code.
In real driver code where we do access registers, shouldn't the driver be responsible for calling smp_mb where appropriate?
Its not about registers at all. Suppose you have following code sequence:
global variable x = 0;
fn-1() { while (1) { spin_lock() if (x == 1) { spin_unlock(); return; } spin_unlock(); } }
And in an interrupt handler
handler() { spin_lock(); x=1;
if (some-other-event) x = 0; spin_unlock(); }
Now, suppose this some-other-event is returning true for us. Then the expected behavior of this code should be, the first function is running an infinite loop.
But for ARMv6 and above normal memory is weakly ordered. i.e. compiler and processor are free to move instructions doing reads writes to memory before and after other instructions. Also, they can break one memory transaction into two and join 2 into one... etc..
Now who will guarantee that, x is always read after taking the lock in function 1? Because if x moves before the instruction doing the increment on spin_lock variable, then value of x may be read when it is made 1 by the handler and so before the lock is released by the handler.
So, it is responsibility of lock,unlock to make sure that instructions executed within lock/unlock must stay within these two and don't jump out. This is not guaranteed with ARMv6 and above.
STREX and LDREX are for atomic load and store on SMP systems
Hope you understood what i am pointing at??
-- viresh