Home > Software engineering >  why this variable is not optimized out
why this variable is not optimized out

Time:10-17

I have a simple snippet where compiler optimized out the variable "done"

#include <pthread.h>
#include <stdbool.h>

bool done = false;

void *func(void *args)
{
    done = true;

    return NULL;
}

main()
{
    pthread_t p1;
    
    pthread_create(&p1, NULL, func, NULL);
    printf("waiting\n");
    
    while(!done)
    {}
    printf("moving on...\n");
}

Here, in absence of volatile keyword, variable "done" is optimized away and run into infinite loop.

I am compiling using:

gcc -O2 volatile.c -lpthread

But when I use simple func() version:

#include <stdbool.h>

bool done = false;

void func()
{
        done = true;

}

main()
{
        func();
        printf("waiting\n");

        while(!done)
        {}
        printf("moving on...\n");
}

But here the variable "done" is not optimized out, what the difference between the two ?

Compiler in second case guessed out the "done" is going to change some how but not in case of Pthread?

My GCC version is:

gcc --version gcc (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609

CodePudding user response:

The variable done is not optimized out in either case. What is optimized out (in both cases) is the read of done in the while loop. That read is hoisted out of the loop and happens once before the loop; the loop then runs 0 times or infinitely depending on the value of done read before the loop. It effectively becomes

    if (!done)
        while (true) {}
    else
        while (false) {}

which is then further simplified to just

    if (!done) while (true) {}

CodePudding user response:

the following proposed code:

  1. includes the missing header file: 'stdio.h' for 'printf()' and 'fprintf()'
  2. properly exits the thread function
  3. properly causes the 'main' thread to wait for the sub thread to avoid 'burning all the available CPU cycles'
  4. properly checks the status of the call to 'pthread_create()' -- this function does not set 'errno'
  5. properly handles the 'args' parameter to avoid a compiler warning
  6. eliminates the 'useless' variable 'done'
  7. uses a valid signature for 'main()'
  8. incorporates appropriate horizontal spacing for readability
  9. eliminates unneeded header 'stdbool.h'

and now, the proposed code:

#include <pthread.h>
#include <stdio.h>  // printf(), fprintf()
#include <stdlib.h> // exit() and EXIT_FAILURE

//bool done = false;

void *func( void *args )
{
    (void)args;   // eliminate warning about unused argument
    //done = true;

    //return NULL;
    pthread_exit( NULL );
}

int main( void )   //use valid signature for 'main()'
{
    pthread_t p1;
    
    if( pthread_create( &p1, NULL, func, NULL ) != 0 )
    {
        fprintf( stderr, "call to pthread_create() failed\n" );
        exit( EXIT_FAILURE );
    }

    printf( "waiting\n" );
    pthread_join( p1, NULL );  // wait for sub thread to exit
    
    //while(!done)
    //{}
    printf( "moving on...\n" );
}
  • Related