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?


Thanks for the quick response.

I looked at the assembly code, and found it a bit strange. Here are
the two while loops in comparison:
while ( g_counter == 0 );
-O0
0x08048567 <main+102>:  mov    0x80497f8,%eax
0x0804856c <main+107>:  test   %eax,%eax
0x0804856e <main+109>:  je     0x8048567 <main+102>

-O1
0x0804853a <main+102>:  mov    0x80497f8,%eax
0x0804853f <main+107>:  test   %eax,%eax
0x08048541 <main+109>:  je     0x8048541 <main+109>    <--- jumping to
itself, so only testing the first time through

So, the -O0 is doing what I would expect, but the -O1 version IS
testing the global variable the first pass, but then never jumping
back to the 0x0804853a to retrieve the new global value and then
re-test. Is this right?

-Tynan

On Thu, Feb 14, 2008 at 10:17 AM, Tony Wetmore
<tony.wetmore@solipsys.com> wrote:
> 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]