I have system with 3 CPUs sharing memory and bus. There is no cache in the system there are however store buffers. CPUs have Compare And Swap (CAS
) instruction available that is atomic. Additionally there are LoadMemoryBarrier()
instruction that ensures loads cannot be reordered across the barrier StoreMemoryBarrier()
ensures that no stores can be reordered across the barrier and GeneralMemoryBarrier()
that ensures no memory access can be reordered across the barrier.
CPUs can reorder stores against stores or loads, loads against stores or loads and either against atomic operations. Basically they can reorder memory access any way they please.
unsigned int spinlock = 0;
int x = 0;
void lock()
{
while (CAS(&spinlock, 1, 0) == 1); // Wait to acquire lock
// Spinlock acquired
LoadMemoryBarrier();
}
void unlock()
{
GeneralMemoryBarrier();
spinlock = 0;
}
void CPU1()
{
lock();
x += 1;
unlock();
}
void CPU2()
{
lock();
x -= 1;
unlock();
}
void CPU3()
{
printf("%d", x);
}
Can store to x
be ordered to happen before spinlock is acquired? My understanding is that no, it cannot be and so I do not see any case where we would need more then LoadMemoryBarrier()
inside of lock()
function. Is my understanding correct and can you provide an example of where this barrier is not enough of a guarantee?
EDIT:
I am using C99 and do not have access to stdatomic. Assume CAS
does not include any implicit barriers.