Datesfat Chicks
5/17/2011 10:24:00 PM
On 16 May 2011 23:18:39 GMT, jt@toerring.de (Jens Thoms Toerring)
wrote:
>aleksa <aleksazr@gmail.com> wrote:
>> sys_handler() calls user_handler() which may call
>> SetRetVal() to change the default RetValue:
>
>> **********************
>> static BOOL RetValue; // should this be volatile?
>
>> BOOL sys_handler (void)
>> {
>> RetValue = FALSE; // set default RetValue before
>> user_handler(); // calling user handler
>> return RetValue; // return RetValue (which may have changed)
>> }
>
>> void SetRetVal (BOOL newretval)
>> {
>> RetValue = newretval;
>> }
>> **********************
>
>> Should RetValue be volatile?
>
>No. The compiler must consider that 'RetVal' becomes changed
>as a side-effect of calling user_handler() - it's completely
>normal that a function called changes a global variable.
>
>You need 'volatile' in three (as far as I am aware of at the
>moment) situations. First, if the compiler can reasonably
>assume that a setting or reading a variable has no effect on
>the outcome of a computation, e.g. with
>
>void delay( int x )
>{
> int i
> for ( i = 0; i < x; i++ )
> ;
>}
>
>the compiler may "see" that changing 'i' has no effect at all
>(neither for the outcome of the function nor by side-effects)
>and thus it (rather likely) will remove the whole loop (or
>even any calls of delay()). In this case qualifying 'i' as
>'volatile' makes a big difference since it keeps the compiler
>from making those assumptions, so it has to produce code that
>runs the complete loop, resulting in some CPU time consumed,
>which was the real intention of the loop.
>
>The second one is when you deal with hardware registers,
>mapped into the address space. Writing to or reading from
>such a register can have side-effects the compiler can't
>know about. So, for example, whe you have
>
>void trigger_the_card( )
>{
> int *x = 0xdeadbeef; /* x now points to a memory-
> mapped register of the card */
> *x;
>}
>
>it will look to the compiler as if nothing reasonable is
>happening here - the result of reading from address 'x'
>is never used. But in reality this is not about the
>value read but reading from the memory-mapped register
>triggers some action but which the compiler doesn't (and
>can't) know about. So using 'volatile' is required.
There is a second reason to declare hardware-mapped registers
volatile: the value may change without the code being compiled
changing it.
For example,
while (HW_REG & 0x1) ;
could, with some optimizations, generate a loop that simply can't
exit. HW_REG may be read once only in the optimized code.
>And, third, there are global variables that may be chan-
>ged asynchronously, i.e. not within the normal program
>flow, e.g. via an interrupt handler. Also in those cases
>the compiler can't forsee this (it assumes that the pro-
>gram it compiles will be runing uninterrupted until the
>very end).
Threads and memory shared between processes are variants of this ...
in effect, they are invoked "indirectly" as the result of an
interrupt.
>But none of this is what happens in the case you describe.
>You have a global variable that can be changed from every
>point in the program (or at least, since it's qualified as
>static, from any place in the translation unit it's defined
>in). Thus the compiler can't assume that it will have the
>same value after a call of some function it had before that
>call. Thus qualifying it as 'volatile' is not needed.
DFC