This is the mail archive of the
gcc-help@gcc.gnu.org
mailing list for the GCC project.
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
> >
> >
>
>