Heads-up: volatile and C++

Robert Dewar dewar@adacore.com
Tue Apr 19 21:27:00 GMT 2005


Paul Koning wrote:
>>>>>>"Robert" == Robert Dewar <dewar@adacore.com> writes:
> 
> 
>  Robert> Ken Raeburn wrote:
>  >> That's what I thought.  So, unless the compiler (or language spec)
>  >> is going to become thread-aware, any data to be shared across
>  >> threads needs to be declared volatile, even if some other
>  >> mechanism (like a mutex) is in use to do some synchronization.
>  >> Which means performance would be poor for any such data.
> 
>  Robert> The use of shared variables without synchronization is rare
>  Robert> in any case in most code.
> 
> You mean "without explicit synchronization" via mutexes or the like?
> 
> It seems that the classic circular buffer communication mechanisms
> have been forgotten by many, but they still work quite well and
> require no mutexes or the like.  All that is required is sufficiently
> ordered memory accesses.

Sure such alogorithms are interesting on mono processors, and that's
EXACTLY the situation in which volatile is appropriate (there is a bit
of confusion in C between what Ada would call volatile and atomic. In
Ada, volatile talks about making sure that reads/writes are to memory,
and atomic is about guaranteeing that access takes a single instruction.

For example, in Ada programming the circular buffer works by making the
buffer itself volatile, and the pointers to the buffer atomic. I am not
sure exactly how this works in C, or whether it is really well defined).

Actually shared variables are quite an interesting topic. If you want
to find out much more about them, have a look at Norman Shulman's NYU
PhD thesis (I was the advisor) which is all about shared variables.
Not sure if it is online somewhere or not. There are a number of
interesting algorithms discussed in this thesis, including the class
of algoritms where different threads work on different parts of a
matrix with overlapped shared variables on the edges.

Nevertheless such usage is relatively rare, and volatile is good enough,
I see no basis for any changes to the compiler.

> I'm using circular buffers to communicate between threads.  I drop
> data into the buffer and move the "in" pointer; the consumer compares
> the pointers, reads data from the buffer, and advances the "out"
> pointer.  The current code has the pointers declared as volatile, buf
> the buffer data area is not (and I wouldn't want it to be -- that
> seems to be a performance issue).

Of course the buffer data area must be declared as volatile, otherwise
the compiler is free to make and hold private copies of elements in
separate threads. It probably won't in practice, but to rely on this
is non-portable.
> 
> So this relies on volatile references acting as barriers to the
> movement of non-volatile references. 

There is no basis for such reliance

> In a coherent memory system (or
> single CPU platform) that's sufficient; in a non-coherent or weakly
> enough ordered system I would add asm("sync") or the like.

You miss the important point that it is just fine for individual
threads to make local copies of memory variables, e.g. in registers,
and so the reads/writes that you expect to be syncrhonized in this way
just aren't there at all.
> 
>        paul




More information about the Gcc mailing list