Hello,
even (or because?) reading the standard (ISO/IEC 9899/1999) I do not
understand some issues with volatile. The background is embedded
programming where data is exchanged between main program flow and
interrupts.
At the organisation I work, instead of declaring a variable volatile,
it is casted to volatile when necessary:
Example 1 (reading):
int flag; // global variable, non-volatile
while( (volatile)flag ) // cast to volatile before reading
;
The reason for this is: when the variable is declared volatile, the
compiler cannot optimize it at all. However, by using the cast to
volatile, one can force volatile behavior in some areas, while others
(e.g. in the interrupt) still can be optimized. Addionally, this can be
used even if the variable declaration is not under my control.
Question: is this covered by the standard?
Since the whole topic of volatile is very complex (e.g. it is related
to pipeling), does somebody know a good article or book which covers
this topic deeply?
BTW, does anybody know how to google an expression like (volatile)
(*including* the bracket)?
Thanks,
Uli G. Margull
nospam@"lastname".de 14 19132 go***************@margull.de writes: Hello,
even (or because?) reading the standard (ISO/IEC 9899/1999) I do not understand some issues with volatile. The background is embedded programming where data is exchanged between main program flow and interrupts.
At the organisation I work, instead of declaring a variable volatile, it is casted to volatile when necessary:
Example 1 (reading): int flag; // global variable, non-volatile while( (volatile)flag ) // cast to volatile before reading ;
The reason for this is: when the variable is declared volatile, the compiler cannot optimize it at all. However, by using the cast to volatile, one can force volatile behavior in some areas, while others (e.g. in the interrupt) still can be optimized. Addionally, this can be used even if the variable declaration is not under my control.
This method doesn't do what you want, which is to say it doesn't
force volatile semantics. Use this instead:
while( *(volatile*) &flag ) ...
Question: is this covered by the standard?
Yes, although perhaps not as directly as it might.
Since the whole topic of volatile is very complex (e.g. it is related to pipeling), does somebody know a good article or book which covers this topic deeply?
A small set of rules for using volatile:
1. Use volatile for variables that might change "unexpectedly".
2. Use volatile for automatic variables in routines that use
setjmp().
3. To force volatile semantics on a particular access, take the
address of the variable and cast it to (volatile WHATEVER *),
dereferencing the cast expression to get the value.
4. Sometimes volatile is a reasonable way to get around problems
with code generation in compilers that have conformance
problems in some areas, eg, the gcc compiler on x86 with
semantics of assigning or casting to double. Don't do
this just haphazardly, since if it's unnecessary code
quality will very likely go down.
5. Unless you really know what you're doing and why you're
doing it, if you're using volatile you're likely doing
something wrong. Try to find another way to solve the
problem, and if you still have to use volatile code
up a nice small example and post to comp.lang.c and
ask for helpful suggestions.
Tim Rentsch <tx*@alumnus.caltech.edu> writes: This method doesn't do what you want, which is to say it doesn't force volatile semantics. Use this instead:
while( *(volatile*) &flag ) ...
Of course what I meant to write was
while( *(volatile int*) &flag ) ...
On Thu, 16 Jun 2005 00:18:03 -0700, google-newsgroups wrote: Hello,
even (or because?) reading the standard (ISO/IEC 9899/1999) I do not understand some issues with volatile. The background is embedded programming where data is exchanged between main program flow and interrupts.
At the organisation I work, instead of declaring a variable volatile, it is casted to volatile when necessary:
Example 1 (reading): int flag; // global variable, non-volatile while( (volatile)flag ) // cast to volatile before reading ;
I assume you mean the cast (volatile int)flag. This doesn't do what you
want. The special behaviour of the const and volatile qualifiers only
applies to lvalues (although type rules apply in other situations). What
the code above does is read the value of flag using non-volatile semantics
then casts that value to volatile int. Since it 9is just a value at this
point and not an lvalue the volatile has no effect. The line is equivalent
to
while (flag)
You would have to write something like
while (*(volatile int *)&flag)
to do what you want. Here the *lvalue* used to read the value of flag has
type volatile int.
The reason for this is: when the variable is declared volatile, the compiler cannot optimize it at all. However, by using the cast to volatile, one can force volatile behavior in some areas, while others (e.g. in the interrupt) still can be optimized.
The whole concept of using a volatile variable as non-volatile in some
areas sounds dangerous. You would probably be better off using a separate
variable for parts that don't need to be volatile. That could make the
compiler optimiser's job easier too.
Addionally, this can be used even if the variable declaration is not under my control.
It sounds like an odd situation. A variable being used in this way should
be defined as volatile. If it isn't that suggests the code defining it
isn't designed for this purpose and probably won't work properly.
Question: is this covered by the standard?
The standard specifies volatile Since the whole topic of volatile is very complex (e.g. it is related to pipeling), does somebody know a good article or book which covers this topic deeply?
volatile itself has nothing to do with pipelining. How volatile might be
implemented on specific architectures is a machine code level topic. If
you are writing in C you let the compiler handle the details.
Also consider the sig_atomic_t type.
Lawrence
Tim Rentsch wrote: Tim Rentsch <tx*@alumnus.caltech.edu> writes:
This method doesn't do what you want, which is to say it doesn't force volatile semantics. Use this instead:
while( *(volatile*) &flag ) ...
Of course what I meant to write was
while( *(volatile int*) &flag ) ...
Doesn't (volatile*) mean the same thing as (volatile int*)?
--
pete
Thanks for your answers sofar. In the meantime, I tested the problem on
a PowerPC platform with a Wind River compiler, with the following
results:
int dummy = 0;
1.
unsigned char flag;
while( (volatile)flag)
dummy++;
The above does not work: the memory is not reloaded in the evaluation
2.
unsigned char flag;
while( (volatile unsigned char)flag )
dummy++;
The above does work: the memory is reloaded every time
3.
unsigned int flag;
while( (volatile unsigned char)flag )
dummy++;
The above does not work: the memory is not reloaded.
At the moment, the proposed solution in the company is to use the
second one (volatile unsigned char), but I see problems with conformity
to ANSI-C.
Thanks again & regards,
Uli Margull
pete <pf*****@mindspring.com> writes: Tim Rentsch wrote: Tim Rentsch <tx*@alumnus.caltech.edu> writes:
This method doesn't do what you want, which is to say it doesn't force volatile semantics. Use this instead:
while( *(volatile*) &flag ) ...
Of course what I meant to write was
while( *(volatile int*) &flag ) ...
Doesn't (volatile*) mean the same thing as (volatile int*)?
Yes I believe it does, but in C99 I think it may require a diagnostic.
In any case I consider '(volatile int*)' to be better style.
On Thu, 16 Jun 2005 10:08:22 +0000, pete wrote: Tim Rentsch wrote: Tim Rentsch <tx*@alumnus.caltech.edu> writes:
> This method doesn't do what you want, which is to say it doesn't > force volatile semantics. Use this instead: > > while( *(volatile*) &flag ) ...
Of course what I meant to write was
while( *(volatile int*) &flag ) ...
Doesn't (volatile*) mean the same thing as (volatile int*)?
It did in C90, but C99 has outlawed "implicit int".
Lawrence
On Thu, 16 Jun 2005 05:16:22 -0700, google-newsgroups wrote: Thanks for your answers sofar. In the meantime, I tested the problem on a PowerPC platform with a Wind River compiler, with the following results:
int dummy = 0;
1. unsigned char flag; while( (volatile)flag) dummy++;
A non-volatile access of flag
The above does not work: the memory is not reloaded in the evaluation
2. unsigned char flag; while( (volatile unsigned char)flag ) dummy++;
Another non-volatile access of flag
The above does work: the memory is reloaded every time
A compiler may choose to implement any object access as volatile if it
wishes, however that doesn't make the code correct.
3. unsigned int flag; while( (volatile unsigned char)flag ) dummy++;
Agaon, a non-volatile access of flag.
The above does not work: the memory is not reloaded.
At the moment, the proposed solution in the company is to use the second one (volatile unsigned char), but I see problems with conformity to ANSI-C.
A couple of people have given a correct solution, why are you considering
3 wrong solutions and ignoring that?
And, again, consider using sig_atomic_t for the integer type.
Lawrence
Lawrence Kirby wrote: On Thu, 16 Jun 2005 10:08:22 +0000, pete wrote: Doesn't (volatile*) mean the same thing as (volatile int*)?
It did in C90, but C99 has outlawed "implicit int".
Thank you.
--
pete
Tim Rentsch wrote: pete <pf*****@mindspring.com> writes: Doesn't (volatile*) mean the same thing as (volatile int*)?
Yes I believe it does, but in C99 I think it may require a diagnostic. In any case I consider '(volatile int*)' to be better style.
Thank you.
I think so too.
I think it's best to write in a style constrained by both
C89 and C99.
int main(void){return 0;}
instead of
main(){return 0;}
or
int main(void){}
--
pete
Hi Lawrence,
thank you everybody for writing your discussion topics, and I assure
you that I am not ignoring any post.
In the company I work (it's a rather big one), the coding guidelines
state that the "cast" to (volatile int) is the correct way to access a
variable that might change from outside (e.g. due to ISR).
In order to change that rule, I do not only have to know what is right
or wrong, but I need an rock-solid argument proving my opinion.
Basically, I have to argue out of the standard. However, I personally
have a hard time reading this from the standard.
Again, thanks for all your posts, and I am not ignoring them.
Yours,
Uli Margull go***************@margull.de writes: In the company I work (it's a rather big one), the coding guidelines state that the "cast" to (volatile int) is the correct way to access a variable that might change from outside (e.g. due to ISR).
In order to change that rule, I do not only have to know what is right or wrong, but I need an rock-solid argument proving my opinion. Basically, I have to argue out of the standard. However, I personally have a hard time reading this from the standard.
I recommend the Rationale document ("Rationale for International
Standard--Programming Languages--C"). In particular, if people
need convincing, quote this paragraph out of section 6.7.3 of the
Rationale document:
A cast of a value to a qualified type has no effect; the
qualification (volatile, say) can have no effect on the access
sinceit has occurred prior to the case. If it is necessary to
access a non-volatile object using volatile semantics, the
technique is to cast the address of the object to the appropriate
pointer-to-qualified type, then dereference that pointer.
Notice the last sentence. In other words, use:
* (volatile WHATEVER *) & non_volatile_object_identifier
The paragraph in question is just before section 6.7.3.1 in the
rationale document. If you also need to quote from the standard
document itself, cite 6.7.3 p3:
The properties associated with qualified types are meaningful
only for expressions that are lvalues.
The expression
(volatile WHATEVER) non_volatile_object_identifier
is _not_ an lvalue, hence the 'volatile' qualifier is meaningless.
Conversely, the expression
* (volatile WHATEVER *) & non_volatile_object_identifier
_is_ an lvalue (it may be placed on the left side of an assignment
statement), so the property of the 'volatile' qualifier has its
intended meaning in this case.
Hi Tim,
thanks a lot. I think this solved my problem.
Now I am looking forward to some interesting discussions here...
Yours,
Uli
In article <11**********************@g47g2000cwa.googlegroups .com>
<go***************@margull.de> wrote: Thanks for your answers sofar. In the meantime, I tested the problem on a PowerPC platform with a Wind River compiler ...
It may be worth noting that there is more than one Wind River
compiler for PowerPC platforms. This is about all that is
at least marginally on-topic here; the rest probably belongs
in comp.os.vxworks.
[In all three examples, "flag" is a non-volatile object, which
will presumably be modified from an interrupt handler. The first
two make it an "unsigned char" and the third an "unsigned int".]
while( (volatile)flag) [does not work as desired] while( (volatile unsigned char)flag ) [does work as desired] while( (volatile unsigned char)flag ) [does not work as desired]
At the moment, the proposed solution in the company is to use the second one (volatile unsigned char), but I see problems with conformity to ANSI-C.
While none of these is "nonstandard", the fact that the second one
happens to work under whatever conditions you have used to test it
is probably mere coincidence.
The *best* solution is to declare "flag" as volatile in the first
place. The second best is to use *(volatile T *)&flag, where T
stands for the actual type of "flag" (unsigned char or unsigned int).
The former will work on all the Wind River compilers, and the latter
will work in all the cases I am aware of (which is nowhere near
"all").
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers. This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: newsock |
last post by:
Why need to qualify a member function "volatile"?
Why need to qualify a object "volatile"?
When need to "const_cast" away "volatile" of an object and a member
function?
I also saw some code...
|
by: Tim Rentsch |
last post by:
Here's another question related to 'volatile'. Consider
the following:
int x;
void
foo(){
int y;
y = (volatile int) x;
|
by: LBJ |
last post by:
lets say i have the following definition:
volatile char* p = 0x0a0a0a;
lets say p now points directly to cacheable memory, and lets also
say that this memory is currently cached. when p is...
|
by: Tim |
last post by:
I'm trying to co-erce a __gc array of Byte to a __nogc pointer to char to
pass to a native function call in a bit of managed c++ code like this:
Byte field __gc = dynamic_cast<Byte...
|
by: steve.j.donovan |
last post by:
Hi guys,
We have the following macro:
#define NEXT(type,p) (*((type*)(p))++)
It provides a way to poke variable sized data into an array of pcode
for a simple VM.
e.g,
|
by: Mark |
last post by:
Hi List,
I want to write a function to copy some data out of a hardware buffer.
The hardware can change the contents of this buffer without it being
written to by my function. I want to use...
|
by: red floyd |
last post by:
I have a struct that maps onto a set of memory mapped registers. I
access this via a pointer.
Is it better to declare it as pointer to a volatile struct, or to
declare the individual members as...
|
by: Felix Kater |
last post by:
I haven't been thinking about it for years but recently I've stumbled on
the fact that 'casting' is actually doing (at least) two different
things:
On the one hand 'casting' means: 'Change...
|
by: CptDondo |
last post by:
I'm trying to write what should be a simple program, and it keeps
hanging if I use volatile....
The program, stripped of its error checking, is this:
unsigned short * start;
unsigned short *...
|
by: MeoLessi9 |
last post by:
I have VirtualBox installed on Windows 11 and now I would like to install Kali on a virtual machine. However, on the official website, I see two options: "Installer images" and "Virtual machines"....
|
by: DolphinDB |
last post by:
The formulas of 101 quantitative trading alphas used by WorldQuant were presented in the paper 101 Formulaic Alphas. However, some formulas are complex, leading to challenges in calculation.
Take...
|
by: Aftab Ahmad |
last post by:
Hello Experts!
I have written a code in MS Access for a cmd called "WhatsApp Message" to open WhatsApp using that very code but the problem is that it gives a popup message everytime I clicked on...
|
by: Aftab Ahmad |
last post by:
So, I have written a code for a cmd called "Send WhatsApp Message" to open and send WhatsApp messaage. The code is given below.
Dim IE As Object
Set IE =...
|
by: ryjfgjl |
last post by:
ExcelToDatabase: batch import excel into database automatically...
|
by: marcoviolo |
last post by:
Dear all,
I would like to implement on my worksheet an vlookup dynamic , that consider a change of pivot excel via win32com, from an external excel (without open it) and save the new file into a...
|
by: isladogs |
last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM).
In this month's session, we are pleased to welcome back...
|
by: Vimpel783 |
last post by:
Hello!
Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
|
by: ArrayDB |
last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
| |