Question

If there are pointers "A" and "B", with a requirement such that any writes to "A" should be made visible before any writes to "B" are made visible. If I am not allowed to use locks and if I am not allowed to declare these variables as "volatile", will the following code guarantee that, the above requirement will be met?

volatile temp;

*A = value1;
temp = *A;

if (temp == value1) {
    *B = value2
}
Was it helpful?

Solution

You will want to use memory barriers or fences: see http://en.wikipedia.org/wiki/Memory_barrier

In the Linux kernel you can use the rmb() or wmb() calls.

Under pthreads you can use pthread_barrier_wait(), though that doesn't appear to be in my pthreads manpages.

On MSVC, look at Force order of execution of C statements? - which also has some good general information.

If you find an 'atomic' library, that will normally include barrier functions.

OTHER TIPS

The answer is simple. You cannot. Reordering can happen because:

  • Compiler will decide to reorder (it is allowed to do so, although this depends on compiler flags, etc);
  • Processor will decide to reorder. If the the processor is complex enough it will definitely do so.

To force memory ordering you need synchronization. Unfortunately there are tons of approaches here. Each approach has its own pros and cons. Depending on your situation you need to pick some.

I think it would be perfectly legal for a C compiler to reorder your example code like this:

volatile temp;

old_b = *B;
*B = value2;    
*A = value1;
temp = *A;

if (temp != value1) {
    *B = old_b;
}

Something like that would probably be better:

volatile temp;

temp = value1;
*A = temp;
temp = value2;
*B = temp;

But even if you know that the store instruction for B appears after the store instruction for A, this still wouldn't guarantee that other threads "see" the modifications in that order. This will depend on cache synchronization and is basically unpredictable. You'll need memory barriers or a locking mechanism to make it work reliably.

No, it won't. And there is no way you can diddle around with volatile and simple C constructs to achieve it either. The compiler is free to reorder your code as long as your program works right (and anybody else be damned!)

So the question is: what other options can you call upon? For example, if the only requirement is that another task never sees updates out of order, you can effectively guarantee that by making any system call between setting A and B. Even a call to a library function in a distant memory location would probably do the job. All you really need to do is to exceed the longest possible pipeline. But that could take a while...

Which brings me to the question: how are you going to test this? And how time critical is it?

Probably need more info to really answer the question.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top