GCC atomic built-in and unstable
I use some globals in a multithreaded program, some of the members are modified by multiple threads at the same time and some others are not.
I have not defined any of these volatile members, but anytime I use these members to read and write, I use atomic built-in functions like __sync_fetch_and_add.
The question is, should I define these members or the entire volatile structure?
I think the compiler should be able to access memory and not any register because of this built in (lock prefix), should I be worried about other members not causing race conditions.
I checked the build output of my compiler (gcc 4.6.2) and my guess seems to be correct.
Here is some test code.
int sum = 0;
for (i=0; i<2000000000; i++) {
sum += i;
}
Build output (-O2 -S -masm = intel)
L2:
add edx, eax
inc eax
cmp eax, 2000000000
jne L2
Therefore the compiler never accesses memory (eax = i, edx = sum)
Here is the second test code.
volatile int sum = 0;
for (i=0; i<2000000000; i++) {
sum += i;
}
Build output
L2:
mov edx, DWORD PTR [esp+28]
add edx, eax
mov DWORD PTR [esp+28], edx
inc eax
cmp eax, 2000000000
jne L2
The compiler accessed memory for the amount each time as expected.
The last code, my way.
int sum = 0;
for (i=0; i<2000000000; i++) {
__sync_fetch_and_add(&sum , i);
}
Build output.
L2:
lock add DWORD PTR [esp+28], eax
inc eax
cmp eax, 2000000000
jne L2
Even the temporary register, as before (edx), the compiler accessed memory every time.
So, I do not define volatile any member that is modified by multiple threads, or only modified one thread at a time. I'm safe?
Thanks in advance.
source to share
Yes, you are safe. The documentation doesn't say they should be volatile, so they shouldn't.
Functions __sync
* act as memory barriers as needed, so volatile
would be overkill. And in any case, this will not allow anything else to be used outside of functions __sync
* (only functions __sync
* generate a prefix lock
).
Note. Features __sync
* were deprecated in gcc 4.7 in favor of C ++ 11-style __atomic
* types , but gcc 4.6 doesn't have them yet.
source to share