This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

volatile keyword needed?



It's not clear to me whether this case requires "volatile" in order to work.  Can someone please comment?

File1.c has a function called foo().  Inside foo() there is a while loop the depends on a global Boolean.  Inside the while loop it calls another function called watchout() that updates the gBool1 variable after some condition has been met.  The watchout() function lives in File2.c.

 

void foo(void)   /* This function lives in File1.c */

{

   gBool1 = TRUE;

   while( gBool1 == TRUE )

   {

       watchout();

    }

}

 

void watchout(void)      /* This function lives in File2.c */

{

   static i =0;

 

   if( i < 100 )

   {

       i++;

   }

   else

   {

      gBool1 == FALSE;

      i = 0;

   }

}

FYI, I did already read this article:

http://processors.wiki.ti.com/index.php/Volatile

Now on the one hand this looks very similar to the semaphore example.  Perhaps I'm reading too much into the use of the word "thread" in the description.  In the case above there would never be any pre-emption involved, i.e. both functions execute as part of the same thread.  Would volatile be required?

Further background...  We're dealing with auto-generated code and I believe there may be a bunch of these sorts of things in the code and I'm wondering if we can safely optimize.  So in other words, we can't simply add volatile and be done.  Every time we regenerate code all the same issues would come back.

 

 

  • Brad,

    My understanding is we don't need 'volatile' in this case because compiler, when it is compiling File1.c, can not have any assumption (or knowledge) about the function watchout() if it was declared 'extern.'

    Regards,
    Atsushi

  • Atsushi is correct, volatile is not needed here.

    The compiler does not know whether calling the function watchout changes the global variable gBool1, so gBool1 will be read each time through the loop.

  • Atsushi/Archaeologist,

    Thanks for your replies.  That's the answer I was hoping to hear!

    I am a little confused though.  In the article on "Volatile" from the wiki there is a very similar example.  In that particular case there was a call to sleep.  I'm confused why that example is considered problematic and yet this example is ok.  In that scenario shouldn't the compiler be under the impression that "sleep" might actually modify the variable?  Of course, it doesn't but the compiler wouldn't know that.  Perhaps that example needs to be adjusted so that it's not making function calls?

  • Yes, the example is wrong.  I'm trying to fix it now, but the site is extremely slow for me at the moment.

  • Hi,

    So if I'm wrong but I think that the example is not wrong, in the beginning of that part we have:

    "If an object can be modified by an interrupt function (or any other external agent or side effect such as DMA, peripheral device, interrupt, another thread, etc), that variable must be declared volatile."

    I think that the intention is to show that when the variable 'semaphore' is used in interrupts, peripherals... it should be declared as volatile. So altough the codes are similar, the way the variable is modified is different.

    Thanks. Regards

    Johannes

  • The key is to consider that the C language only understands a single thread of execution.  The compiler usually only knows about the explicit accesses of a variable that are on the single thread.  If a variable can be modified from outside that thread (e.g. an interrupt), the compiler would have no way of knowing that without "volatile."

  • Archaeologist, thanks for updating the Volatile wiki page.

    Johannes, please see the updated example on the volatile wiki page I referenced in the original post.  Now that the function call within the loop has been removed that code will fail.  The reason is as you stated, i.e. the flag will change without the compiler knowing (i.e. it happens asynchronously due to an interrupt).  In the case where we call sleep within the loop it will behave differently.  In the case where we are calling sleep() the compiler has absolutely no idea what happens in the sleep() function, e.g. in the "mind" of the compiler it's entirely possible that sleep() itself will modify the variable.  For this reason the code works fine if you are calling sleep() inside the loop.  Or in my case the watchout() function works fine.