volatile variable using in making application - c

I am new in this field. Previously I was doing microcontroller programming where I used volatile variables to avoid compiler optimization. But I never saw such volatile declaration before variable declaration. Does it mean compilation is done without any optimization in Arago build. Here I have two questions.
How can I enable different types of optimization during compilation like speed and space optimization in Angstrom build?
If it is already an optimized compilation, why do we not need volatile declarations?

If you are using gcc for compilation then add/modify CFLAGS
-O2 or -O3 to enable a bunch of generic performance optimisations.
Os to enable code size optimisations.
A long list of flags that control individual gcc compiler optimisation options is available here.
Most often volatile is used NOT for optimising the code, but to ensure validity of data.
The declaration of a variable as volatile tells the compiler that the variable can be modified at any time externally to the implementation by
the operating system
another thread of execution
-- interrupt routine
-- signal handler
underlying hardware
As the value of a volatile-qualified variable can change at any time, the actual variable must always be accessed whenever the variable is referenced in code.
This means the compiler cannot perform optimizations on the variable. Marking a variable volatile forces the compiler to generate code that ignores the variable in the CPU register and actually reads the underlying memory/hardware-register mapped at the address referred-to by the variable.
Also checkout the various aspects of using volatile along-with compiler optimisations.

Related

Is it necessary to use the "volatile" qualifier even in case the GCC optimisations are turned off?

My question is targeted towards the embedded development, specifically STM32.
I am well aware of the fact that the use of volatile qualifier for a variable is crucial when dealing with a program with interrupt service routines (ISR) in order to prevent the compiler optimising out a variable that is used in both the ISR and the main thread.
In Atollic TrueSTUDIO one can turn off the GCC optimisations with the -O0 flag before the compilation. The question is, whether it is absolutely necessary to use the volatile qualifier for variables that are used inside and outside the ISR, even when the optimisations are turned off like this.
With optimizations disabled it seems unlikely that you'd need volatile. However, the compiler can do trivial optimizations even at O0. For example it might remove parts of the code that it can deduct won't be used. So not using volatile will be a gamble. I see no reason why you shouldn't be using volatile, particularly not if you run with no optimizations on anyway.
Also, regardless of optimization level, variables may be pre-fetch cached on high end MCUs with data cache. Whether volatile solves/should solve this is debatable, however.
“Programs must be written for people to read, and only incidentally for machines to execute.”
I think here We can use this quote. Imagine a situation (as user253751 mentioned) you remove keyword volatile from every variable because there is optimization enabled. Then few months later you have to turn optimization on. Do you imagine what a disaster happened?
In addition, I work with code where there is an abstraction layer above bare-metal firmware and there we use volatile keyword when variable share memory space between those layers to be sure that we use exact proper value. So there this another usage of volatile not only in ISRs, that means there is not easy to change this back and be sure that everything works ok.
Debugging code where variable should be volatile is not so hard but bugs like this looks like something magic happened and you don't know why because for example something happened one in 10k execution of that part of code.
Summary: There is no strict "ban" for removing volatile keyword when optimization is turned off but for me is VERY bad programming practice.
I am well aware of the fact that the use of volatile qualifier for a variable is crucial when dealing with a program with interrupt service routines (ISR) in order to prevent the compiler optimising out a variable that is used in both the ISR and the main thread.
You should actually keep in mind that volatile is not a synchronization construct.
It does not force any barriers, and does not prevent reordering with other non-volatile variables. It only tells the compiler not to reorder the specific access relative to other volatile variables -- and even then gives no guarantees that the variables won't be reordered by the CPU.
That's why GCC will happily compile this:
volatile int value = 0;
int old_value = 0;
void swap(void)
{
old_value = value;
value = 100;
}
to something like:
// value will be changed before old_value
mov eax, value
mov value, 100
mov old_value, eax
So if your function uses a volatile to signal something like "everything else has been written up to this point", keep in mind that it might not be enough.
Additionally, if you are writing for a multi-core microcontroller, reordering of instructions done by the CPU will render the volatile keyword completely useless.
In other words, the correct approach for dealing with synchronization is to use what the C standard is telling you to use, i.e. the <stdatomic.h> library. Constructs provided by this library are guaranteed to be portable and emit all necessary compiler and CPU barriers.

Shall I use register class variables in modern C programs?

In C++, the keyword register was removed in its latest standard ISO/IEC 14882:2017 (C++17).
But also in C, I see a lot, that more and more coders tend to not use or like to declare an object with the register class qualifier because its purposed benefit shall be almost useless, like in #user253751´s answer:
register does not cause the compiler to store a value in a register. register does absolutely nothing. Only extremely old compilers used register to know which variables to store in registers. New compilers do it automatically. Even 20-year-old compilers do it automatically.
Is the use of register class variables and with that the use of the keyword register deprecated?
Shall I use register class variables in my modern programs? Or is this behavior redundant and deprecated?
There is no benefit to using register. Modern compilers substantially ignore it — they can handle register allocation better than you can. The only thing it prevents is taking the address of the variable, which is not a significant benefit.
None of my own code uses register any more. The code I work on loses register when I get to work on a file — but it takes time to get through 17,000+ files (and I only change a file when I have an external reason to change it — but it can be a flimsy reason).
As #JonathanLeffler stated it is ignored in most cases.
Some compilers have a special extension syntax if you want to keep the variable in the particular register.
gcc Global or local variable can be placed in the particular register. This option is not available for all platforms. I know that AVR & ARM ports implement it.
example:
register int x asm ("10");
int foo(int y)
{
x = bar(x);
x = bar1(x);
return x*x;
}
https://godbolt.org/z/qwAZ8x
More information: https://gcc.gnu.org/onlinedocs/gcc-6.1.0/gcc/Explicit-Register-Variables.html#Explicit-Register-Variables
But to be honest I was never using it in my programming life (30y+)
It's effectively deprecated and offers no real benefit.
C is a product of the early 1970s, and the register keyword served as a hint to the compiler that a) this particular object was going to be used a lot, so b) you might want to store it somewhere other than main memory - IOW, a register or some other "fast" memory.
It may have made a difference then - now, it's pretty much ignored. The only measurable effect is that it prevents you from taking the address of that object.
First of all, this feature is NOT deprecated because: "register" in this context (global or local register variables) is a GNU extension which are not deprecated.
In your example, R10 (or the register that GCC internally assigns REGNO(reg) = 10), is a global register. "global" here means, that all code in your application must agree on that usage. This is usually not the case for code from libraries like libc, libm or libgcc because they are not compiled with -ffixed-10. Moreover, global registers might conflict with the ABI. avr-gcc for example might pass values in R10. In avr-gcc, R2...R9 are not used by the ABI and not by code from libgcc (except for 64-bit double).
In some hard real-time app with avr-gcc I used global regs in a (premature) optimization, just to notice that the performance gain was miniscule.
Local register variables, however, are very handy when it comes to integrating non-ABI functions for example assembly functions that don't comply to the GCC ABI, without the need for assembly wrappers.

How do I "tell" to C compiler that the code shouldn't be optimized out?

Sometimes I need some code to be executed by the CPU exactly as I put it in the source. But any C compiler has it's optimization algorithms so I can expect some tricks. For example:
unsigned char flag=0;
interrupt ADC_ISR(){
ADC_result = ADCH;
flag = 1;
}
void main(){
while(!flag);
echo ADC_result;
}
Some compilers will definitely make while(!flag); loop infinitive as it will suppose flag equals to false (!flag is therefore always true).
Sometimes I can use volatile keyword. And sometimes it can help. But actually in my case (AVR GCC) volatile keyword forces compiler to locate the variable into SRAM instead of registers (which is bad for some reasons). Moreover many articles in the Internet suggesting to use volatile keyword with a big care as the result can become unstable (depending on a compiler, its optimization settings, platform and so on).
So I would definitely prefer to somehow point out the source code instruction and tell to the compiler that this code should be compiled exactly as it is. Like this: volatile while(!flag);
Is there any standard C instruction to do this?
The only standard C way is volatile. If that doesn't happen to do exactly what you want, you'll need to use something specific for your platform.
You should indeed use volatile as answered by David Schwartz. See also this chapter of GCC documentation.
If you use a recent GCC compiler, you could disable optimizations in a single function by using appropriate function specific options pragmas (or some optimize function attribute), for instance
#pragma GCC optimize ("-O0");
before your main. I'm not sure it is a good idea.
Perhaps you want extended asm statements with the volatile keyword.
You have several options:
Compile without optimisations. Unlike some compilers, GCC doesn't optimise by default so unless you tell it to optimise, you should get generated code which looks very similar to your C source. Of course you can choose to optimise some C files and not others, using simple make rules.
Take the compiler out of the equation and write the relevant functions in assembly. Then you can get exactly the generated code you want.
Use volatile, which prevents the compiler from making any assumptions about a certain variable, so for any use of the variable in C the compiler is forced to generate a LOAD or a STORE even if ostensibly unnecessary.

is register data type variables are limited?

i totally stucked with this question, i had heard that there are 5 to 10 variables only can declare having datatype of register. i wish to know how many register datatype variables would be declare.it is pretty to seem. but this level of understanding we required while executing a programs.otherwise we mightstuck at runtime while execution thanks for your answers in advance
1).is registers(for datatypes) are vary to different types of compilers/machines??
2).how many register datatype variables could we pick ?
3).what are all these registers?(i mean cpu reg, memory reg, general purpose reg???)
register is no more a useful keyword in C programs compiled by a recent C optimizing compiler (e.g. recent versions of GCC or Clang/LLVM).
Today, it simply means that a variable qualified as register cannot be the operand of the & unary address-of operator (notice that register is a qualifier like const or volatile are, not a data type like int).
In the 1990s, register was then an important keyword for compilers.
The compiler (when optimizing) does a pretty good job about register allocation and spilling.
Try to compile your favorite C function with e.g. gcc -Wall -O2 -fverbose-asm -S; you'll get an assembly file suffixed .s and you could look inside it; the compiler is doing pretty well about register allocation.
Notice that GCC provides language extensions to put a few global (or local) variables in explicit registers. This is rarely useful, and it is target processor and ABI specific.
BTW, on desktop or laptop processors, the CPU cache matters a lot more than the registers (see references and hints in this answer to another question).
In C there is no way to explicitely define variable in CPU registers. You may barely hint a compiler with register specifier, but there is no point to do it nowadays, as compilers have sophisticated optimizer, which takes care of registers allocation.
do not use register. The optomizer will do a better job

How to do optimization in C. Is there any need of volatile keyword if i set optimization level to none(-0)

I am not understanding a simple thing, if we set optimization level to none(means don't optimize) then is there necessary to use volatile keyword in C.
Turning off optimization does not mean broken code will start working. Anything that would need to be volatile with optimization on must be volatile with optimization off. For example, without a volatile modifier, access to the variable might be cached in a register instead of properly interfacing with whatever it's supposed to interface with.
I think it is a nice question but answer is probably it is completely up to the compiler.
Assuming you want to use volatile to not reorder volatile reads / writes and -O0 to keep program order.
For example GCC doc states:
-fno-toplevel-reorder
Do not reorder top-level functions, variables, and asm statements.
Output them in the same order that they appear in the input file. When
this option is used, unreferenced static variables are not removed.
This option is intended to support existing code that relies on a
particular ordering. For new code, it is better to use attributes when
possible.
Enabled at level -O0. When disabled explicitly, it also implies -fno-section-anchors, which is otherwise enabled at -O0 on some targets.
Of course correct way is still to use volatile properly rather than relying on program order and -O0 flag.
There is also no guarantee that even in -O0 compiler might not do some optimizations.

Resources