This is the mail archive of the
gcc-help@gcc.gnu.org
mailing list for the GCC project.
Re: confused at code generation for a empty loop
- From: kum <a dot kumaresh at gmail dot com>
- To: PRC <panruochen at gmail dot com>
- Cc: gcc-help <gcc-help at gcc dot gnu dot org>
- Date: Fri, 30 Nov 2007 14:45:39 +0530
- Subject: Re: confused at code generation for a empty loop
- References: <200711301445245306580@gmail.com>
while you use
static int flag = 0;
gcc is free to read the flag only once (optimisation) in any loop. To
inform this to the compiler you have to make use of volatile type
modifier. This will force the compiler to load the flag every time it
tests it.
By the way using some synch object (like semaphore) you can do the
same job better.
-kum
On Nov 30, 2007 12:15 PM, PRC <panruochen@gmail.com> wrote:
> Here is my code:
> =================================================================================
> #include <pthread.h>
> #include <stdio.h>
> #define NUM_THREADS 1
> static int flag = 0;
> void *thread(void *threadid)
> {
> int ret = rand();
> printf("thread return %d!\n", ret);
> sleep(10);
> flag = 1;
> return (void *)ret;
> }
>
> int main (int argc, char *argv[])
> {
> pthread_t threads[NUM_THREADS];
> int rc;
> rc = pthread_create(&threads[0], NULL, thread, (void *)0);
> if (rc){
> printf("ERROR; return code from pthread_create() is %d\n", rc);
> exit(-1);
> }
> while( flag == 0 ) ;
> return 0;
> }
> =================================================================================
> gcc -O2 -g -lpthread a.c
> objdump -S a.out > a.S
>
>
> `cat a.S` shows:
> =================================================================================
> if (rc){
> 80484d4: 85 c0 test %eax,%eax
> 80484d6: 75 15 jne 80484ed <main+0x4d>
> 80484d8: a1 68 97 04 08 mov 0x8049768,%eax
> 80484dd: 85 c0 test %eax,%eax
> 80484df: 90 nop
> printf("ERROR; return code from pthread_create() is %d\n", rc);
> exit(-1);
> }
> while( flag == 0 ) ;
> 80484e0: 74 fe je 80484e0 <main+0x40>
> ================================================================================
> You can see the variable `flag` is read only once. If the value of `flag` is 0 at the first time,
> the program will trap into a dead loop and never exit. And gcc knows the value of `flag` could
> be modified in the routine `thread`.
>
>
> But if I modify the line "while( flag == 0 ) ;" to "while(flag == 0) printf("waiting..\n");"
> and recompile the source code, the output assembly code becomes:
> =================================================================================
> while( flag == 0 ) printf("waiting..\n");
> 8048510: c7 04 24 74 86 04 08 movl $0x8048674,(%esp)
> 8048517: e8 90 fe ff ff call 80483ac <puts@plt>
> 804851c: a1 b8 97 04 08 mov 0x80497b8,%eax
> 8048521: 85 c0 test %eax,%eax
> 8048523: 74 eb je 8048510 <main+0x40>
> =================================================================================
> `flag` is read in each loop. Then when the value of `flag` is modified, the loop terminates.
>
> I wonder why gcc generates code for a empty loop like that. Is it a bug or for optimization in some case?
>
> My gcc is:
> 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 --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.1 20060525 (Red Hat 4.1.1-1)
>
>