Reputation: 33
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
}
Upvotes: 3
Views: 191
Reputation: 10557
The answer is simple. You cannot. Reordering can happen because:
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.
Upvotes: 2
Reputation: 33618
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.
Upvotes: 1
Reputation: 10868
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.
Upvotes: 0
Reputation: 25119
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.
Upvotes: 3