How to safely convert/copy volatile variable? - c

volatile char* sevensegment_char_value;
void ss_load_char(volatile char *digits) {
...
int l=strlen(digits);
...
}
ss_load_char(sevensegment_char_value);
In the above example I've got warning from avr-gcc compiler
Warning 6 passing argument 1 of 'strlen' discards 'volatile' qualifier from pointer target type [enabled by default]
So I have to somehow copy the value from volatile to non-volatile var? What is the safe workaround?

There is no such thing like a "built in" Workaround in C. Volatile tells the compiler, that the contents of a variable (or in your case the memory the variable is pointing at) can change without the compiler noticing it and forces the compiler to read the data direct from the data bus rather than using a possibly existing copy in the registers.
Therefore the volatile keyword is used to avoid odd behaviour induced through compiler optimizations. (I can explain this further if you like)
In your case, you have a character buffer declared as volatile. If your program changes the contents of this buffer in a different context like an ISR for example, you have to implement sort of a synchronisation mechanism (like disabling the particular interrupt or so) to avoid inconsistency of data. After aquiring the "lock" (disabling the interrupt) you can copy the data byte by byte to a local (non-volatile) buffer and work on this buffer for the rest of the routine.
If the buffer will not change "outside" of the context of your read accesses I suggest to omit the volatile keyword as there is no use for it.
To judge the correct solution, a little bit more information about your exact use case would be needed.

Standard library routines aren't designed to work on volatile objects. The simplest solution is to read the volatile memory into normal memory before operating on it:
void ss_load_char(volatile char *digits) {
char buf[BUFSIZE];
int i = 0;
for (i = 0; i < BUFSIZE; ++i) {
buf[i] = digits[i];
}
int l=strlen(buf);
...
}
Here BUFSIZE is the size of the area of volatile memory.
Depending on how the volatile memory is configured, there may be routines you are supposed to call to copy out the contents, rather than just using a loop. Note that memcpy won't work as it is not designed to work with volatile memory.

The compiler warning only means that strlen() will not treat your pointer as volatile, i.e. it will maybe cache the pointer in a register when computing the length of your string. I guess, that's ok with you.
In general, volatile means that the compiler will not cache the variable. Look at this example:
extern int flag;
while (flag) { /* loop*/ }
This would loop forever if flag != 0, since the compiler assumes that flag is not changed "from the outside", like a different thread. If you want to wait on the input of some other thread, you must write this:
extern volatile int flag;
while (flag) { /* loop*/ }
Now, the compiler will really look at flag each time the loop loops. This may be must more what we intended in this example.
In answer to your question: if you know what you're doing, just cast the volatile away with int l=strlen((char*)digits).

Related

Passing volatile variable as constant argument in a function

I'm developing and Embedded code for a Cortex-M0 MC where I declare a variable as volatile char TOS_Mins_Char[3];
to store some values during an ISR which would be periodically changed.
I want to convert these characters to an integer using the atoi() function,
but atoi() has its argument type as pointer to a constant string: int atoi(const char *); This give me error unless I avoid the volatile keyword in the variable declaration. (Faced similar situation in other std functions also)
Is there any solution for this other than writing a user defined
function?
If I use const char TOS_Mins_Char[3];, will it be a problem?
Is it mandatory to use the volatile keyword, what is its use in
contrast to an ARM MC ?
The volatile keyword is necessary to tell the compiler to reload the characters from memory for each access.
If you know the array will not be modified during the conversion, you can use a cast to silence the warning:
int value = atoi((const char*)TOS_Mins_Char);
Note that the value returned by atoi() might be completely bogus if the interrupt routine modifies the array in the middle of the conversion. You can prevent this by disabling the interrupts around accesses to the array. To minimize the duration of processing with disabled interrupts, you might want to copy the array to a local array this way:
char buf[sizeof TOS_Mins_Char];
CLI; // whatever macro use to disable interrupts
memcpy(buf, TOS_Mins_Char, sizeof TOS_Mins_Char);
STI; // enable interrupts
int value = atoi(buf);
The problem with this approach is the non reentrency of the interrupt disable/enable mechanism: if interrupts are already disabled when entering the code, they will be enabled upon leaving, which is probably not intended and a likely cause of bugs in the calling code.
Another quick and dirty trick can be used to lower the likelihood of an interrupt clash:
int value, last = atoi((const char*)TOS_Mins_Char);
while ((value = atoi((const char*)TOS_Mins_Char)) != last) {
last = value;
}
If the buffer was modified by the ISR during the conversion, the next conversion would produce a different result. The is a remove possibility that the next conversion also be interrupted by the ISR, but in a non life critical system, you might want to ignore this possibility.

Clear variable on the stack

Code Snippet:
int secret_foo(void)
{
int key = get_secret();
/* use the key to do highly privileged stuff */
....
/* Need to clear the value of key on the stack before exit */
key = 0;
/* Any half decent compiler would probably optimize out the statement above */
/* How can I convince it not to do that? */
return result;
}
I need to clear the value of a variable key from the stack before returning (as shown in the code).
In case you are curious, this was an actual customer requirement (embedded domain).
You can use volatile (emphasis mine):
Every access (both read and write) made through an lvalue expression of volatile-qualified type is considered an observable side effect for the purpose of optimization and is evaluated strictly according to the rules of the abstract machine (that is, all writes are completed at some time before the next sequence point). This means that within a single thread of execution, a volatile access cannot be optimized out or reordered relative to another visible side effect that is separated by a sequence point from the volatile access.
volatile int key = get_secret();
volatile might be overkill sometimes as it would also affect all the other uses of a variable.
Use memset_s (since C11): http://en.cppreference.com/w/c/string/byte/memset
memset may be optimized away (under the as-if rules) if the object modified by this function is not accessed again for the rest of its lifetime. For that reason, this function cannot be used to scrub memory (e.g. to fill an array that stored a password with zeroes). This optimization is prohibited for memset_s: it is guaranteed to perform the memory write.
int secret_foo(void)
{
int key = get_secret();
/* use the key to do highly privileged stuff */
....
memset_s(&key, sizeof(int), 0, sizeof(int));
return result;
}
You can find other solutions for various platforms/C standards here: https://www.securecoding.cert.org/confluence/display/c/MSC06-C.+Beware+of+compiler+optimizations
Addendum: have a look at this article Zeroing buffer is insufficient which points out other problems (besides zeroing the actual buffer):
With a bit of care and a cooperative compiler, we can zero a buffer — but that's not what we need. What we need to do is zero every location where sensitive data might be stored. Remember, the whole reason we had sensitive information in memory in the first place was so that we could use it; and that usage almost certainly resulted in sensitive data being copied onto the stack and into registers.
Your key value might have been copied into another location (like a register or temporary stack/memory location) by the compiler and you don't have any control to clear that location.
If you go with dynamic allocation you can control wiping that memory and not be bound by what the system does with the stack.
int secret_foo(void)
{
int *key = malloc(sizeof(int));
*key = get_secret();
memset(key, 0, sizeof(int));
// other magical things...
return result;
}
One solution is to disable compiler optimizations for the section of the code that you dont want optimizations:
int secret_foo(void) {
int key = get_secret();
#pragma GCC push_options
#pragma GCC optimize ("O0")
key = 0;
#pragma GCC pop_options
return result;
}

Why does this function cast an int argument to a volatile pointer and immediately dereferences it?

I just want to know what below function is doing
static int myfunc(int val)
{
return *(volatile int *)val;
}
If val is a pointer when you pass it to this function, it makes sure that the value pointed by this pointer is read and returned to the caller.
I suspect this might be a trick for embedded devices, where sometimes the operation of reading a value at an address has some effect on the hardware.
For instance, reading from an hardware FIFO will pop the read value from the FIFO.
Marking here the pointer as volatile make the compiler not optimize the read if it detects that the value is not used.
Example:
#define FIFO_ADDRESS 0x800050
static int myfunc(int val)
{
return *(volatile int *)val; // the address *will* be read
}
static int bad( int val )
{
return *(int*)val; // might be optimized to nop()
// by the compiler if the value
// is not used by the caller
}
int main(){
bad( FIFO_ADDRESS ); // could be NOP since return value is not used
myfunc( FIFO_ADDRESS ); // *WILL* perform a READ operation on the FIFO,
// even though the result is not used, because
// of the volatile keyword
}
Note that I would do it differently, probably with a smartly named macro:
#define FORCE_INT_PTR_READ( address ) *(volatile int *)address
Could you give us an example of usage in your case?
It appears to be trying to confuse the optimiser (and possibly the user). It is taking an integer, treating it as a pointer to an integer, and dereferencing it. The 'volatile' ensures that the optimiser will generate code for that dereference at that point and won't let the optimiser omit the fetch from memory. This is usually used for accessing memory mapped hardware registers,
It does the following:
Passes a signed integer to a function.
Converts the contents of the signed integer to a pointer. This doesn't make sense, since pointers cannot be signed. Formally, this is also not well-defined behavior and anything can happen.
The volatile keyword suggests that the contents of val should equal to a physical hardware address. When reading from such addresses, the volatile keyword is necessary, since the hardware register's contents may change at any time.
It takes the contents of that address and treats it as int, which is then returned.
static means that the function has local scope.
Please note that if the target OS uses virtual addressing (such as a PC), the OS will just give you a slap on the fingers should you attempt to run this code.
All in all, this is poorly written code, which is neither safe, well-defined nor portable. You won't gain any valuable knowledge by staring at it.
It casts val to a pointer and returns it's value. Calls to myfunc() will work only if thy look like
int i, j;
i = 10;
j = myfunc( (int)&i )`
That should set j to 10
BUT it won't work on 64bit systems where sizeof(int *) is 8 and thus larger then sizeof(int) or on some old systems with sizeof(int) == 2

Volatile keyword in C [duplicate]

This question already has answers here:
Why is volatile needed in C?
(18 answers)
Closed 9 years ago.
I am writing program for ARM with Linux environment. its not a low level program, say app level
Can you clarify me what is the difference between,
int iData;
vs
volatile int iData;
Does it have hardware specific impact ?
Basically, volatile tells the compiler "the value here might be changed by something external to this program".
It's useful when you're (for instance) dealing with hardware registers, that often change "on their own", or when passing data to/from interrupts.
The point is that it tells the compiler that each access of the variable in the C code must generate a "real" access to the relevant address, it can't be buffered or held in a register since then you wouldn't "see" changes done by external parties.
For regular application-level code, volatile should never be needed unless (of course) you're interacting with something a lot lower-level.
The volatile keyword specifies that variable can be modified at any moment not by a program.
If we are talking about embedded, then it can be e.g. hardware state register. The value that it contains may be modified by the hardware at any unpredictable moment.
That is why, from the compiler point of view that means that compiler is forbidden to apply optimizations on this variable, as any kind of assumption is wrong and can cause unpredictable result on the program execution.
By making a variable volatile, every time you access the variable, you force the CPU to fetch it from memory rather than from a cache. This is helpful in multithreaded programs where many threads could reuse the value of a variable in a cache. To prevent such reuse ( in multithreaded program) volatile keyword is used. This ensures that any read or write to an volatile variable is stable (not cached)
Generally speaking, the volatile keyword is intended to prevent the compiler from applying any optimizations on the code that assume values of variables cannot change "on their own."
(from Wikipedia)
Now, what does this mean?
If you have a variable that could have its contents changed at any time, usually due to another thread acting on it while you are possibly referencing this variable in a main thread, then you may wish to mark it as volatile. This is because typically a variable's contents can be "depended on" with certainty for the scope and nature of the context in which the variable is used. But if code outside your scope or thread is also affecting the variable, your program needs to know to expect this and query the variable's true contents whenever necessary, more than the normal.
This is a simplification of what is going on, of course, but I doubt you will need to use volatile in most programming tasks.
In the following example, global_data is not explicitly modified. so when the optimization is done, compiler thinks that, it is not going to modified anyway. so it assigns global_data with 0. And uses 0, whereever global_data is used.
But actually global_data updated through some other process/method(say through ptrace ). by using volatile you can force it to read always from memory. so you can get updated result.
#include <stdio.h>
volatile int global_data = 0;
int main()
{
FILE *fp = NULL;
int data = 0;
printf("\n Address of global_data:%x \n", &global_data);
while(1)
{
if(global_data == 0)
{
continue;
}
else if(global_data == 2)
{
;
break;
}
}
return 0;
}
volatile keyword can be used,
when the object is a memory mapped io port.
An 8 bit memory mapped io port at physical address 0x15 can be declared as
char const ptr = (char *) 0x15;
Suppose that we want to change the value at that port at periodic intervals.
*ptr = 0 ;
while(*ptr){
*ptr = 4;//Setting a value
*ptr = 0; // Clearing after setting
}
It may get optimized as
*ptr = 0 ;
while(0){
}
Volatile supress the compiler optimization and compiler assumes that tha value can
be changed at any time even if no explicit code modify it.
Volatile char *const ptr = (volatile char * )0x15;
Used when the object is a modified by ISR.
Sometimes ISR may change tha values used in the mainline codes
static int num;
void interrupt(void){
++num;
}
int main(){
int val;
val = num;
while(val != num)
val = num;
return val;
}
Here the compiler do some optimizations to the while statement.ie the compiler
produce the code it such a way that the value of num will always read form the cpu
registers instead of reading from the memory.The while statement will always be
false.But in actual scenario the valu of num may get changed in the ISR and it will
reflect in the memory.So if the variable is declared as volatile the compiler will know
that the value should always read from the memory
volatile means that variables value could be change any time by any external source. in GCC if we dont use volatile than it optimize the code which is sometimes gives unwanted behavior.
For example if we try to get real time from an external real time clock and if we don't use volatile there then what compiler do is it will always display the value which is stored in cpu register so it will not work the way we want. if we use volatile keyword there then every time it will read from the real time clock so it will serve our purpose....
But as u said you are not dealing with any low level hardware programming then i don't think you need to use volatile anywhere
thanks

Is function call a memory barrier?

Consider this C code:
extern volatile int hardware_reg;
void f(const void *src, size_t len)
{
void *dst = <something>;
hardware_reg = 1;
memcpy(dst, src, len);
hardware_reg = 0;
}
The memcpy() call must occur between the two assignments. In general, since the compiler probably doesn't know what will the called function do, it can't reorder the call to the function to be before or after the assignments. However, in this case the compiler knows what the function will do (and could even insert an inline built-in substitute), and it can deduce that memcpy() could never access hardware_reg. Here it appears to me that the compiler would see no trouble in moving the memcpy() call, if it wanted to do so.
So, the question: is a function call alone enough to issue a memory barrier that would prevent reordering, or is, otherwise, an explicit memory barrier needed in this case before and after the call to memcpy()?
Please correct me if I am misunderstanding things.
The compiler cannot reorder the memcpy() operation before the hardware_reg = 1 or after the hardware_reg = 0 - that's what volatile will ensure - at least as far as the instruction stream the compiler emits. A function call is not necessarily a 'memory barrier', but it is a sequence point.
The C99 standard says this about volatile (5.1.2.3/5 "Program execution"):
At sequence points, volatile objects are stable in the sense that previous accesses are
complete and subsequent accesses have not yet occurred.
So at the sequence point represented by the memcpy(), the volatile access of writing 1 has to occurred, and the volatile access of writing 0 cannot have occurred.
However, there are 2 things I'd like to point out:
Depending on what <something> is, if nothing else is done with the the destination buffer, the compiler might be able to completely remove the memcpy() operation. This is the reason Microsoft came up with the SecureZeroMemory() function. SecureZeroMemory() operates on volatile qualified pointers to prevent optimizing writes away.
volatile doesn't necessarily imply a memory barrier (which is a hardware thing, not just a code ordering thing), so if you're running on a multi-proc machine or certain types of hardware you may need to explicitly invoke a memory barrier (perhaps wmb() on Linux).
Starting with MSVC 8 (VS 2005), Microsoft documents that the volatile keyword implies the appropriate memory barrier, so a separate specific memory barrier call may not be necessary:
http://msdn.microsoft.com/en-us/library/12a04hfd.aspx
Also, when optimizing, the compiler
must maintain ordering among
references to volatile objects as well
as references to other global objects.
In particular,
A write to a volatile object (volatile write) has Release
semantics; a reference to a global or
static object that occurs before a
write to a volatile object in the
instruction sequence will occur before
that volatile write in the compiled
binary.
A read of a volatile object (volatile read) has Acquire semantics;
a reference to a global or static
object that occurs after a read of
volatile memory in the instruction
sequence will occur after that
volatile read in the compiled binary.
As far as I can see your reasoning leading to
the compiler would see no trouble in moving the memcpy call
is correct. Your question is not answered by the language definition, and can only be addressed with reference to specific compilers.
Sorry to not have any more-useful information.
My assumption would be that the compiler never re-orders volatile assignments since it has to assume they must be executed at exactly the position where they occur in the code.
It's probalby going to get optimized, either because the compiler inlines the mecpy call and eliminates the first assignment, or because it gets compiled to RISC code or machine code and gets optimized there.
Here is a slightly modified example, compiled with gcc 7.2.1 on x86-64:
#include <string.h>
static int temp;
extern volatile int hardware_reg;
int foo (int x)
{
hardware_reg = 0;
memcpy(&temp, &x, sizeof(int));
hardware_reg = 1;
return temp;
}
gcc knows that the memcpy() is the same as an assignment, and knows that temp is not accessed anywhere else, so temp and the memcpy() disappear completely from the generated code:
foo:
movl $0, hardware_reg(%rip)
movl %edi, %eax
movl $1, hardware_reg(%rip)
ret

Resources