Thread: looking help to understand volatile keyword

  1. #1
    Registered User
    Join Date
    Feb 2022
    Posts
    73

    looking help to understand volatile keyword

    I am trying to understand the following paragraph but i have read it many time, still I don't have any idea

    A "volatile" in a variable declaration tells us and the compiler that the value of that variable may change at any time, by some means outside the normal flow of this section of code. These changes may be caused by hardware i.e. a peripheral, another processor in a multiprocessor system, or an interrupt service routine.The "volatile" keyword tells the compiler not to make certain optimizations that only work with "normal" variables stored in RAM or ROM that are completely under the control of this C program.
    The entire point of embedded programming is its communications with the outside world -- and both input and output devices require the "volatile" keyword.
    There are at least 3 types of optimizations that "volatile" turns off:

    • "read" optimizations -- without "volatile", C compilers assume that once the program reads a variable into a register, it doesn't need to re-read that variable every time the source code mentions it, but can use the cached value in the register. This works great with normal values in ROM and RAM, but fails miserably with input peripherals. The outside world, and internal timers and counters, frequently change, making the cached value stale and irrelevant.


    • "write" optimizations -- without "volatile", C compilers assume that it doesn't matter what order writes occur to different variables, and that only the last write to a particular variable really matters. This works great with normal values in RAM, but fails miserably with typical output peripherals. Sending "turn left 90, go forward 10, turn left 90, go forward 10" out the serial port is completely different than "optimizing" it to send "0" out the serial port.


    • instruction reordering -- without "volatile", C compilers assume that they can reorder instructions. The compiler may decide to change the order in which variables are assigned to make better use of registers. This may fail miserably with IO peripherals where you, for example, write to one location to acquire a sample, then read that sample from a different location. Reordering these instructions would mean the old/stale/undefined sample is 'read', then the peripheral is told to acquire a new sample (which is ignored).

    Depending on your hardware and compiler capabilities, other optimizations (SIMD, loop unrolling, parallelizing, pipelining) may also be affected.

    I am taking following code just for example

    Code:
    #include<stdio.h>
    
    uint8_t flag;
    
    
    int main (void)
    {
    	flag == 0
    	...
       while(flag == 1) 
       {
        ...
       }
    	
    	return 0;
    }
    
    
    
    
    ...
    ISR() 
    {
        flag = 1;
    }
    I am looking someone who can explain with example

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    A better example.
    Code:
    int flag;
    int main (void)
    {
       flag = 0;
        ...
       while(flag == 0) 
       {
           // no code here changes flag
       }
       // the ISR just happened
         
        return 0;
    }
     
    ISR() 
    {
        flag = 1;
    }
    This may be an example of "read" optimizations.
    If the compiler can determine that there are no code execution paths through the while loop that could possibly change flag, it might deduce that the code is
    Code:
       while ( true )
       {
           // no code here changes flag
       }
    volatile ensures that the compiler does actually re-read the flag value from memory on a periodic basis.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Feb 2022
    Posts
    73
    I found that if the word volatile is used it prevents the compiler from optimizing.

    C compilers compile each source file individually.

    I'm just trying to understand what optimization means.

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    > I'm just trying to understand what optimization means.
    Optimization Definition & Meaning - Merriam-Webster

    Code:
    $ cat foo.c
    int flag = 0;
    int main (void)
    {
       flag = 0;
       while(flag == 0) 
       {
       }
       return 0;
    }
    $ gcc -S foo.c
    $ grep -P "^[a-z\.]|^\t[a-z]" foo.s
    flag:
    main:
    .LFB0:
    	endbr64
    	pushq	%rbp
    	movq	%rsp, %rbp
    	movl	$0, flag(%rip)
    	nop
    .L2:
    	movl	flag(%rip), %eax  // each time around the loop, flag is loaded and tested
    	testl	%eax, %eax
    	je	.L2
    	movl	$0, %eax
    	popq	%rbp
    	ret
    .LFE0:
    Now with optimisation.
    Code:
    $ gcc -S -O2 foo.c
    $ grep -P "^[a-z\.]|^\t[a-z]" foo.s
    main:
    .LFB0:
    	endbr64
    	movl	$0, flag(%rip)  // flag is loaded only ONCE
    .L2:
    	jmp	.L2  // and the loop runs endlessly - aka while(true)
    .LFE0:
    flag:
    Now with volatile.
    Code:
    $ cat foo.c
    volatile int flag = 0;
    int main (void)
    {
       flag = 0;
       while(flag == 0) 
       {
       }
       return 0;
    }
    $ gcc -S -O2 foo.c
    $ grep -P "^[a-z\.]|^\t[a-z]" foo.s
    main:
    .LFB0:
    	endbr64
    	movl	$0, flag(%rip)
    .L2:
    	movl	flag(%rip), %eax  // and we're back to testing flag each time.
    	testl	%eax, %eax
    	je	.L2
    	xorl	%eax, %eax
    	ret
    .LFE0:
    flag:
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    Another example:
    Code:
    unsigned char or( unsigned char *p ) { return *p |= 0; }
    unsigned char or2( volatile unsigned char *p ) { return *p |= 0; }
    This will give:
    Code:
    or:
      movzx eax,byte [rdi]
      ret
    
    or2:
      movzx eax,byte [rdi]
      mov [rdi],al
      ret
    The or() function do nothing with *p because oring with 0 is to do nothing. But, since the pointer points to a volatile object in or2(), the compiler has to write the value back (oring STILL do nothing), as intended by |= operator.

    Where is this useful? With some memory mapped I/O registers of devices (or device memory mapped in the processor address space, like video framebuffers).
    Last edited by flp1969; 02-05-2022 at 07:07 AM.

  6. #6
    Registered User
    Join Date
    Feb 2022
    Posts
    45
    As flp1969 says, the volatile keyword is for when you have a memory resource that is shared in some way and could be altered by something other than the program itself; for example, a memory-mapped device, or a buffer shared between two processes. The volatile modifier tells the compiler not to perform certain optimizations which might skip changes to the memory address, or more to the point, not to assume that the value won't change unexpectedly (e.g., by saving the value in a register rather than accessing the memory directly). It has the effect of ensuring that accesses to the memory address are always performed, even if it would (under normal circumstances) not be strictly necessary to compute something.

    In practice, volatile mostly gets used in things like device drivers, though as I said it can appear when writing certain types of inter-process (or inter-thread) communication. While such elements generally will also be either assigned to a specific process or else protected with a mutex of some sort, that's a separate/orthogonal issue to volatile.
    Last edited by Schol-R-LEA-2; 02-05-2022 at 09:49 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. what is use of volatile keyword in c
    By skyr6546 in forum C Programming
    Replies: 1
    Last Post: 11-20-2019, 09:49 AM
  2. volatile keyword
    By Satya in forum C Programming
    Replies: 1
    Last Post: 03-31-2016, 07:01 AM
  3. Doubt regarding the volatile keyword
    By 2001goran in forum C Programming
    Replies: 2
    Last Post: 03-14-2013, 12:10 PM
  4. Volatile Keyword!!
    By maven in forum C Programming
    Replies: 8
    Last Post: 12-06-2005, 12:56 PM
  5. volatile keyword help!!!!
    By penney in forum Linux Programming
    Replies: 2
    Last Post: 03-12-2003, 08:09 AM

Tags for this Thread