C optimization of extern global variables - c

In case I have a C file that uses an extern declared variable
and in the code the variable is modified and then an external function is called.
will the compiler optimization take into account the possibility that the variable can be touched by the function? so it won't change the C code order and make sure the variable is set in memory before the function is called?

You need to be careful of a number of things... but in a basic C application with a single thread, yes... this should be fine.
If, however you are (non-exhaustive):
Using multiple threads
Using shared memory between a number of processes
Running on a low-level system (e.g: AVR / STM32) and handling the variable in the an interrupt handler and under main()
Handling the variable in a signal handler and under main()
Reading memory / registers that are modified by hardware / DMA
Then you'll need to be careful.
The volatile keyword can be useful - it will inform the compiler that "this variable may change while you're not looking".
Even with the volatile keyword though, you may run into the Read-Modify-Write problem...
Knowing about the Read-Modify-Write problem is half the fight... the other half is mitigating it, which can be achieved by a number of optiosn such as using a technique called Mutual Exclusion / Critical Sections, or if appropriate by copying the data into a local variable before you operate on the value.

Related

C: Using static volatile with "getter" function and interruptions

Suppose I have the following C code:
/* clock.c */
#include "clock.h"
static volatile uint32_t clock_ticks;
uint32_t get_clock_ticks(void)
{
return clock_ticks;
}
void clock_tick(void)
{
clock_ticks++;
}
Now I am calling clock_tick (i.e.: incrementing clock_ticks variable) within an interruption, while calling get_clock_ticks() from the main() function (i.e.: outside the interruption).
My understanding is that clock_ticks should be declared as volatile as otherwise the compiler could optimize its access and make main() think the value has not changed (while it actually changed from the interruption).
I wonder if using the get_clock_ticks(void) function there, instead of accessing the variable directly form main() (i.e.: not declaring it as static) can actually force the compiler to load the variable from memory even if it was not declared as volatile.
I wonder this as someone told me this could be happening. Is it true? Under which conditions? Should I always use volatile anyway no matters if I use a "getter" function?
A getter function doesn't help in any way here over using volatile.
Assume the compiler sees you've just fetched the value two lines above and not changed it since then.
If it's a good optimizing compiler, I would expect it to see the function call has no side effect simply optimize out the function call.
If get_clock_ticks() would be external (i.e. in a separate module), matters are different (maybe that's what you remember).
Something that can change its value outside normal program flow (e.g. in an ISR), should always be declared volatile.
Don't forget that even if you currently compile the code declaring get_clock_ticks and the code using it as separate modules, perhaps one day you will use link-time or cross-module optimisation. Keep the "volatile" even though you are using a getter function - it will do no harm to the code generation in this case, and makes the code correct.
One thing you have not mentioned is the bit size of the processor. If it is not capable of reading a 32-bit value in a single operation, then your get_clock_ticks() will sometimes fail as the reads are not atomic.

'static volatile' vs. 'static' vs. 'volatile' in C

What's the difference between using the variable specifiers static volatile combined? Or using one alone; like static or volatile in microcontroller programming?
static - in this case makes the variable visible only inside the current file
volatile - it is information for the compiler that the object can be changed by something outside the normal execution path (for example, the interrupt routine) and guarantees that the variable will be read before any use and written after every change. volatile (which is a very common misunderstanding) does not guarantee anything else - no atomicity, no cache coherency, etc., etc.
static:
A static variable refers to a class variable that's shared among all instances.
volatile:
Volatile variables are those which are read and written to main memory. They aren't stored in local cache and are always fetched from main memory.
For example, two threads use, say, private volatile int x;. If thread A write(x) and thread B read(x) then, both the times it will write and read from main memory, without using the threads' local cache.
static volatile:
Even if the static variables are shared variables, but in different thread there can be different values for a static variable in the local cache of a thread. To make it consistent for all threads, just declare it as static volatile. So each time it will fetch from main memory.
Many good answers were provided here, but no mention of scope.
Static variables once initialized and later changed within a scope, they retain the changes and never be destroyed or initialized again especially when leaving the scope. Not unless dictated in code. You can say, static variables resemble global variables in terms of their lifecycle but can only be accessed throughout their own scope.
The volatile part has the tendency to force execution to fetch a variable from RAM and not the cached copy in registers or flash. Suppose for example a certain code was submitted to the compiler under certain level of optimization setting. The compiler does not assume any further conditions are attached to variables other than to clear them when they are not used or outside their scope. There are inherently dual uses for volatile, either to disregard optimization offered by the compiler for that variable, or to refrain from using the prefetched copy of that variable except for the one in RAM.
The static volatile is the combination of both behaviors, persistence of that variable in RAM beyond any optimization.
Potential areas of application:
Flash programming
Cyclical buffers
Ring buffers
Concurrency and multiprocessing/multithreading
For the keywords static and volatile there is written enough...
See for example:
Why is volatile needed in C?
What does "static" mean in C?
In the concern of the TWI interface, volatile is needed, because functions which modify these variables could be called from different interrupt service handlers. If volatile would be removed, the compiler will optimize code, not knowing that code can be interrupted. That may lead to failures.

Where all to use volatile keyword in C

I know volatile keyword prevents compiler from optimizing a variable and read it from memory whenever it is read. Apart from memory mapped registers, what are all the situations where we need to use volatile? Given a conforming compiler, do I have to declare test_var as volatile in both scenarios?
1.
In file1.c
int test_var=100;
void func1()
{
test_var++;
}
In file2.c
extern int test_var;
void func2()
{
if(test_var==100)
{
....
}
}
2.
In file1.c
int test_var=100;
void func1()
{
}
In file2.c
extern int test_var;
void func2()
{
if(test_var==100)
{
....
}
}
memory mapped I/O is the only generic use of volatile in C. *)
With POSIX signals, a volatile can also be used together with the type sig_atomic_t like this:
volatile sig_atomic_t signal_occured = 0;
Neither of your scenarios should require volatile at all. If all you're interested in is a guarantee that the value is updated between different compilation units, see tofro's comment, extern already guarantees that. Particularly, volatile is not the correct tool for thread synchronization in C. It would only introduce bugs, because, as you state it, it does require actual read and write accesses to the variable, but it does not enforce their proper ordering with respect to threads (it's missing memory barriers, google for details).
Note that this is different from some other languages where volatile is designed to work between threads.
In an embedded system, volatile might be good enough for communicating between an ISR (interrupt service routine) and the main program, when combined with a data type that's read/written atomically, just like sig_atomic_t for POSIX signals. Consult the documentation of your compiler for that.
*) The C standard mentions this, along with the use-case of "asynchronously interrupting functions", only in a footnote, because memory-mapped I/O is outside the scope of the language. The language just defines the semantics of volatile in a way that make it suitable for memory-mapped I/O.
In neither of your examples is volatile necessary.
volatile is necessary:
anywhere a variable may be changed outside of the control of a single thread of execution,
anywhere the variable access is required to occur even when it semantically has no effect.
Case 1 includes:
memory mapped I/O registers,
memory used for DMA transfers,
memory shared between interrupt and/or thread contexts,
memory shared between independent processors (such as dual port RAM)
Case 2 includes:
loop counters used for empty delay loops, where the entire loop may otherwise be optimised away completely and take no time,
Variables written to but never read for observation in a debugger.
The above examples may not be exhaustive, but it is the semantics of volatile that are key; the language only has to perform an explicit access as indicated by the source code.
Besides extensions such as memory mapped devices, in standard C volatile has two use cases: interaction with signal handlers and modification of objects across usage of setjmp/longjmp. Both are case were there is unusual flow of control that an optimizer may not be aware of.
In C microcontroller applications using interrupts, the volatile keyword is essential in making sure that a value set in an interrupt is saved properly in the interrupt and later has the correct value in the main processing loop. Failure to use volatile is perhaps the single biggest reason that timer-based interrupts or ADC (analog-digital conversion) based interrupts for example will have a corrupted value when flow of control resumes after the processor state is returned post-interrupt. A canonical template from Atmel and GCC:
volatile uint8_t flag = 0;
ISR(TIMER_whatever_interrupt)
{
flag = 1;
}
while(1) // main loop
{
if (flag == 1)
{
<do something>
flag = 0;
}
}
Without the volatile it's guaranteed to not work as expected.
Apart from memory mapped registers, what are all the situations where
we need to use volatile?
If
execution is purely sequential (no threads and no signals delivered asynchronously);
you don't use longjmp;
you don't need to be able to debug a program compiled with optimizations;
you don't use constructs with vaguely specified semantics like floating point operations;
you don't do useless computations (computations where the result is ignored) as in a benchmark loop;
you don't do timings of any pure computations, that is anything that isn't I/O based (I/O based such as timings of accesses of network requests, external database accesses)
then you probably have no need for volatile.

What does while(!volatile); do?

I saw this in a part that never gets called in a coworker's code:
volatile unsigned char vol_flag = 0;
// ...
while(!vol_flag);
vol_flag is declared in the header file, but is never changed. Am I correct that this will lead to the program hanging in an infinite loop? Is there a way out of it?
Usually a code like this indicates that vol_flag is expected to be changed externally at some point. Here, externally may mean a different thread, an interrupt handler, a piece of hardware (in case of memory mapped IO) etc. This loop effectively waits for the external event which changes the flag.
The volatile keyword is a way for the programmer to express the fact that it is not safe to assume what is apparent from the code: namely that the flag is not changed in the loop. Thus, it prevents the compiler from making optimizations which could compromise the intentions behind the code. Instead, the compiler is forced to make a memory reference to fetch the value of the flag.
Note that (unlike in Java) volatile in C/C++ does not establish happens-before relationship and does not guarantee any ordering or visibility of memory references across volatile access. Moreover, it does not ensure atomicity of variable references. Thus, it is not a tool for communication between threads. See this for details.

Why cant register variables be made global?

While reading from a site a read that you can not make a global variable of type register.Why is it so?
source:
http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=/com.ibm.xlcpp8l.doc/language/ref/regdef.htm
In theory, you could allocate a processor register to a global scope variable - that register would simply have to remain allocated to that variable for the whole life of the program.
However, C compilers don't generally get to see the entire program during the compile phase - the C standard was written so that each translation unit (roughly corresponding to each .c file) could be compiled independently of the others (with the compiled objects later linked into a program). This is why global scope register variables aren't allowed - when the compiler is compiling b.c, it has no way to know that there was a global variable allocated to a register in a.c (and that therefore functions in b.c must preserve the value in that register).
Actually, GCC allows this. A declaration in global scope in the form:
register int foo asm ("r12");
Allocates the register "r12" (on x86_64) for the global "foo". This has a number of limitations and the corresponding manual page is probably the best reference to all the hassle global register variables would make:
http://gcc.gnu.org/onlinedocs/gcc/Explicit-Reg-Vars.html
Because it would be senseless. Global variables exist all the time the application is working. There surely is no free processor register for such a long time ;)
The register keyword has a different meaning than what its name seems to indicate, nowadays it has not much to do with a register of the processing environment. (Although it probably once was chosen for this.) The only text that constrains the use of a variable that is declared with register is this
The operand of the unary & operator
shall be either a function designator,
the result of a [] or unary *
operator, or an lvalue that designates
an object that is not a bit-field and
is not declared with the register
storage-class specifier
So it implements a restriction to automatic variables (those that you declare in a function) such that it is an error to take the address of such a variable. The idea then is that the compiler may represent this variable in whatever way pleases, as a register or as an immediate assembler value etc. You as a programmer promise that you wouldn't take an address of it. Usually this makes not much sense for global variables (they have an address, anyhow).
To summarize:
No, the register keyword is not
ignored.
Yes, it can only be used for stack
variables if you want to be standard conformant
Originally, register variables were meant to be stored in processor registers, but global variables have to be stored in the data or the BSS section to be accessible from every function. Today, compilers don't interpret the register storage class strictly, so it remains largely for compatibility reasons.
The register word is used in C/C++ as request to the compiler to use registers of processor like variables. A register is a sort of variable used by CPU, very very fast in access because it isn't located in memory (RAM). The use of a register is limited by the architecture and the size of the register itself (this mean that some could be just like memory pointers, other to load special debug values and so on).
The calling conventions used by C/C++ doesn't use general registers (EAX, EBX and so on in 80x86 Arch) to save parameters (But the returned value is stored in EAX), so you could declare a var like register making code faster.
If you ask to make it global you ask to reserve the register for all the code and all your source. This is impossible, so compiler give you an error, or simply make it a usual var stored in memory.
Some compilers provide a means of dedicating a register permanently to a variable. The register keyword, however, is insufficient. A compiler's decision to allocate the local variables for a routine in registers generally does not require coordination with anything in other source modules (while some development systems do register optimization between routines, it's far more common to simply define the calling convention so that all routines are allowed to freely alter certain registers (so a caller is responsible for saving the contents if they're needed after the function call) but must not alter others (so the called routine is responsible for saving and restoring the contents if the registers are needed in the function). Thus, a linker doesn't need to concern itself with register usage.
Such an approach is fine for local register variables, but useless for global ones. For global register variables to be useful, the programmer must generally tell the compiler which register is to be used for what variable, and make sure that such reservations are known to the compiler when compiling all modules--even those that don't use the register otherwise. This can be useful in embedded systems, especially with variables that are used by interrupts, but there's usually a very limited number (e.g. 2 or so) of such variables allowed in a system.
So do we all agree now? Do we all see that making a global variable a register variable would be a really, really bad idea? If the original C definition did not forbid it, it was probably because nobody thought anyone would actually implement it that way -- as they should not have especially back in CISC days.
Besides: modern optimizing compilers do a better job of deciding when to keep variables in registers than humans can do. If yours can't do it, then you really, REALLY need to get a better compiler.
Because they're in registers. It's a contradiction in terms.

Resources