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.

+3


source to share


1 answer


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.

+2


source







All Articles