What is the proper use of volatile?

R

red floyd

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 volatile?

That is to say, which is likely to be better/less error prone:

struct registers {
unsigned long reg1;
unsigned long reg2;
};
registers volatile *register_set;

or

struct registers {
unsigned long volatile reg1;
unsigned long volatile reg2;
};
registers *register_set;
 
V

Victor Bazarov

red said:
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 volatile?

That is to say, which is likely to be better/less error prone:

struct registers {
unsigned long reg1;
unsigned long reg2;
};
registers volatile *register_set;

or

struct registers {
unsigned long volatile reg1;
unsigned long volatile reg2;
};
registers *register_set;

I think that if your registers can individually change, you need to
individually name them volatile. Reflects the true nature of them
better, methinks.

V
 
R

red floyd

Victor said:
I think that if your registers can individually change, you need to
individually name them volatile. Reflects the true nature of them
better, methinks.

Yeah, I had pretty much decided that, too. It's always nice to get some
validation/confirmation, though. Also lets me declare them "const
volatile" where needed.

Thanks, Victor.

red floyd
 
K

Kaz Kylheku

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 volatile?

Definitely the individual members. The reason is that this helps to
contain volatile from spreading throughout your program.
That is to say, which is likely to be better/less error prone:

struct registers {
unsigned long reg1;
unsigned long reg2;};

registers volatile *register_set;

See, the trouble is that now you cannot pass this into any function
that just takes a plain ``volatile *'' parameter. And so now you have
to start introducing volatile into function parameters and other local
variables all over the place.

If you ever have this type of structure and you need to put it into a
linked list, e.g.

struct dma_ring_buffer {
unsigned long reg1;
volatile dma_ring_buffer *next;
};

Now the volatile has invaded the interior of the structure: the member
``next'' is a pointer to a qualified structure in order that a
volatile-qualified pointer can be assigned to it.
or

struct registers {
unsigned long volatile reg1;
unsigned long volatile reg2;};

registers *register_set;

The end effect on the access semantics is the same. If P is a pointer
to a volatile-qualified structure then P->M, where M is a member of
that structure, is also volatile qualified. It makes no difference
which way you do it; either way ptr->reg1 accesses a volatile-
qualified unsigned long.

So pick the way that creates the fewest qualifier-related headaches in
your code.
 
P

Pavel

red said:
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 volatile?

That is to say, which is likely to be better/less error prone:

struct registers {
unsigned long reg1;
unsigned long reg2;
};
registers volatile *register_set;

or

struct registers {
unsigned long volatile reg1;
unsigned long volatile reg2;
};
registers *register_set;
Although the above considerations of Victor and Kaz can be valid in some
contexts, here is the one that may suggest the opposite solution:

Sometimes (often?) you would only want one instance of a structure to be
volatile (or, say, one per CPU...) -- for example where it is mapped
onto the particular hardware-specific memory range. If, additionally,
you need to store other instances of your set of registers, and
especially manipulate with these stored instances in a computationally
heavy way, you may want to avoid the runtime overhead of volatile in
those manipulations; in such a situation, you would have to define 2
structures instead of one if you selected the "volatile individual
members" approach whereas the "whole volatile structure" approach would
not require that.

-Pavel
 
T

Taran

Although the above considerations of Victor and Kaz can be valid in some
contexts, here is the one that may suggest the opposite solution:

Sometimes (often?) you would only want one instance of a structure to be
volatile (or, say, one per CPU...) -- for example where it is mapped
onto the particular hardware-specific memory range. If, additionally,
you need to store other instances of your set of registers, and
especially manipulate with these stored instances in a computationally
heavy way, you may want to avoid the runtime overhead of volatile in
those manipulations; in such a situation, you would have to define 2
structures instead of one if you selected the "volatile individual
members" approach whereas the "whole volatile structure" approach would
not require that.

-Pavel- Hide quoted text -

- Show quoted text -

Just curious. What prevents from using const_cast to remove the
volatile-ness for manipulating the structure and the saving it again
(not really sure if cast back to voltile would be necessary again) .
Since the strcuture is not volatile qualified the affects on the
hardware if any due to the change in values are intended to be
discarded; the intermediate values of compuatation would be cached.

I agree with Kaz, I've seen code where the strcutures were volatile
instead of the individual members and the whole code was literred with
const_cast to remove volatile-ness. I'd rather, as Kaz says, keep the
individual members are volatile, since this is the true representation
of the behaviour and wihtout a const_cast literred code.
 
R

red floyd

Kaz said:
Definitely the individual members. The reason is that this helps to
contain volatile from spreading throughout your program.


See, the trouble is that now you cannot pass this into any function
that just takes a plain ``volatile *'' parameter. And so now you have
to start introducing volatile into function parameters and other local
variables all over the place.

If you ever have this type of structure and you need to put it into a
linked list, e.g.

struct dma_ring_buffer {
unsigned long reg1;
volatile dma_ring_buffer *next;
};

Now the volatile has invaded the interior of the structure: the member
``next'' is a pointer to a qualified structure in order that a
volatile-qualified pointer can be assigned to it.

This is a consideration that I hadn't thought of, and it's a very good
argument in favor of making the individual members volatile rather than
the struct itself.

This struct is actually a private member of an enclosing class, so that
nobody else sees it. But as I mentioned in my reply to Victor, I'd
pretty much decided that this is the way to go anyways.

I want to thank everyone for their feedback, as it provided some good
food for thought for future designs.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,794
Messages
2,569,641
Members
45,355
Latest member
SJLChristi

Latest Threads

Top