This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Curious global variable bug? Bad assumptions on my part?


Tynan,

I think the difference is that when GCC optimizes the code, it eliminates the g_counter variable entirely, since it "never changes" within the body of the loop, so the loop becomes "while(false) ;".

When you add the "volatile" qualifier, you are instructing GCC not to optimize the variable away, since its value may change in ways that are unpredictable by GCC.

If you look at the assembly code generated in the -O0 and -O1 cases, the difference should be very obvious in this simple test case.

--
Tony Wetmore


Tynan Wilke wrote:
Hello list,

If I am posting in the wrong place, I apologize. I was making some
test scripts this morning and found a pretty glaring difference
between my optimized (-O1) versus my unoptimized (-O0) test code.
Below, is the a quick example that I made showing the problem:
--------------------------------
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

static int g_counter = 0;

void *IncThread(void* nothing)
{
    printf("Thread started\n");
    while( 1 )
    {
        g_counter++;
//        printf("thread g_counter: %d\n", g_counter );
    }
    return NULL;
}

int main()
{
    pthread_t thread;
    if ( 0 != pthread_create(&thread, NULL, IncThread, NULL ) )
    {
        perror("Failed to create thread");
        exit(1);
    }

    printf("Waiting for counter...\n");
    while ( g_counter == 0 );

    while ( g_counter < 1000000 )
        printf("g_counter: %d\n", g_counter);

    printf("Done!\n");
    return 0;
}
--------------------------------

And compile as follows:
$ gcc -O0 -lpthread main.c -o out

When run, gives the expected output:
$ ./out
Waiting for counter...
Thread started
g_counter: 734
g_counter: 9198
g_counter: 10334
g_counter: 11109
... snip ...
g_counter: 986568
g_counter: 987310
Done!

If I compile with -O1, the issue arrises:
$ gcc -O1 -lpthread main.c -o out
$ ./out
Waiting for counter...
Thread started

And nothing else is printed out since it is stuck on the first while
loop because g_counter is remains 0 in the main thread (but it is
getting incremented in IncThread). I get the same results if g_counter
is not static. The code works fine if I make g_counter volatile.

Here is the gcc version I'm using, which is straight from the RH repo:
$ gcc -v
Using built-in specs.
Target: i386-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man
--infodir=/usr/share/info --enable-shared --enable-threads=posix
--enable-checking=release --with-system-zlib --enable-__cxa_atexit
--disable-libunwind-exceptions --enable-libgcj-multifile
--enable-languages=c,c++,objc,obj-c++,java,fortran,ada
--enable-java-awt=gtk --disable-dssi --enable-plugin
--with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre
--with-cpu=generic --host=i386-redhat-linux
Thread model: posix
gcc version 4.1.2 20070626 (Red Hat 4.1.2-14)

Also, I'm on a quad-core Xeon, if that makes a difference.

I have to imagine that this is due to some bad assumptions on my end,
but I would really like to know why optimising this relatively
straightforward code causes it to behave differently. Any help is
greatly appreciated.

Thanks,
Tynan




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]