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: confused at code generation for a empty loop


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)
>
>


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