471,092 Members | 1,128 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,092 software developers and data experts.

volatile and multiple threads

Is volatile necessary anymore? I have a two-thread piece of code I've been
testing to figure out what volatile does (fairly simple code, uses
pthreads). I have an update thread (variables passed as volatile) and a
print thread (one variable volatile, the other, not). There is no difference
in the behavior of the volatile and nonvolatile thread.

I'm compiling this with gcc, using the -O2 and -pthreads flags.

The sudocode is at the end. The result I'm getting is that the correct
memory addresses and values are being printed by the volatile and
non-volatile variable. If I understand things correctly, the non-volatile
variables should give the wrong addresses at least half the time. Is GCC
just smart enough to handle this, or am I completely misunderstanding
things. I can provide the code, but I'd rather not clutter up the list with
it, without a request.

Thanks,
-Jim Stapleton

* two pointers (a, b) are global (non volatile) variables. Each is of type
(int*)
* each is malloc'ed and the value in the allocated memory set to the value
of a counter variable (0).
* A global volatile turn variable is set to 0 (0 = print, 1 = update).
* the print and update functions are called.

* print function
** output that the print function was called
** call the internal print function with a non-volatile pointer to a
(int**), and a volatile pointer to b (volatile int**)
** output that the print function is closing
** exit

* internal print function
** wait until turn = 0
** loop until count = 5
*** print the memory addresses a & b point to, and the values stored therein
*** set turn to 1
*** wait until turn = 0
** exit

* update function
** output that the update function was called
** call the internal update function with a volatile pointer to a (volatile
int**), and a volatile pointer to b (volatile int**)
** output that the update function is closing
** exit

* internal update function
** wait until turn = 1
** loop until count = 5
*** increment count
*** assign integer pointers (int*) t1 and t2 to the memory values pointed to
by the arguments (eqiv to t1 = a, t2 = b)
*** malloc new memory to a and b (sizeof(int)), and set the value to the
same as count.
*** print out eqiv: "*t1 (t1) -*a (a) *t2 (t2) -*b (b)"
*** free t1 and t2
*** set turn = 0
*** wait until turn = 1
** exit


Jul 10 '08 #1
10 3135
In article <g5**********@charm.magnus.acs.ohio-state.edu>,
S James S Stapleton <st**********@osu.eduwrote:
>Is volatile necessary anymore? I have a two-thread piece of code
Threads are not part of the C programming language itself.
Your system's implementation of threads might (or might not)
have imposed constraints on the generated code such that
everything worked out okay in your particular program on
that particular implementation (on that particular hardware.)

Is volatile necessary anymore? Try writing a C program
on an embedded platform that has memory-mapped I/O registers,
such that reading a register fetches the "next" input value.
On such systems, you don't want the compiler optimizing away
references to the location because it figures the reference
is just going to generate the same value as last time; you
also don't want the compiler introducing new references to the
location figuring that it doesn't need to remember the value
because the value will still be there when it is needed next.

I do not know whether volatile is of any theoretical benefit in
variables shared between pthreads; for that you should consult
comp.programming.threads or the like.
--
"There is no greater calling than to serve your fellow men.
There is no greater contribution than to help the weak.
There is no greater satisfaction than to have done it well."
-- Walter Reuther
Jul 10 '08 #2
Is volatile necessary anymore? Try writing a C program
on an embedded platform that has memory-mapped I/O registers,
such that reading a register fetches the "next" input value.
On such systems, you don't want the compiler optimizing away
references to the location because it figures the reference
is just going to generate the same value as last time; you
also don't want the compiler introducing new references to the
location figuring that it doesn't need to remember the value
because the value will still be there when it is needed next.
OK, I kept seeing references to embedded systems when I was look at things
regarding this. I assume then that they have more agressively optimising
compilers? Would volatile thus be less useful in a non-embedded system?
I do not know whether volatile is of any theoretical benefit in
variables shared between pthreads; for that you should consult
comp.programming.threads or the like.
Thanks, I'll check that out.

-Jim Stapleton
Jul 10 '08 #3
S James S Stapleton <st**********@osu.eduwrote:
Is volatile necessary anymore? Try writing a C program
on an embedded platform that has memory-mapped I/O registers,
such that reading a register fetches the "next" input value.
On such systems, you don't want the compiler optimizing away
references to the location because it figures the reference
is just going to generate the same value as last time; you
also don't want the compiler introducing new references to the
location figuring that it doesn't need to remember the value
because the value will still be there when it is needed next.
OK, I kept seeing references to embedded systems when I was look at things
regarding this. I assume then that they have more agressively optimising
compilers?
It's not because of the optimization being more aggresive. If
you have a hardware register mapped to memory and you can achieve
a certain effect by writing to that address, then you must make
sure that the write really happens. If the memory address isn't
marked as volatile the comiler is allowed to make up a copy of
what gets written there in a register instead of really writing
it out since it can't know that this write has side-effects.
Would volatile thus be less useful in a non-embedded system?
It's not only embedded systems, also hardware drivers for opera-
ting systems will use volatile. But you can also see the diffe-
rence with a "normal" program, just try

#include <limits.h>
int main( void )
{
volatile int i;
for ( i = 0; i < INT_MAX; i++ )
/* empty */ ;
return 0;
}

If you remove the 'volatile' the compiler will rather likely opti-
mize out the whole loop, drastically reducing the execution time.

But volatile can also be useful for signal handlers to make sure
the part of a program accessing a flag that gets set in a signal
handler doesn't use an out of date copy in a register (but then
you usually also throw 'sig_atomic' into the mix to avoid partial
reads).
Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de
Jul 10 '08 #4
"S James S Stapleton" <st**********@osu.eduwrote:

(Walter Roberson) wrote:
>Is volatile necessary anymore? Try writing a C program
on an embedded platform that has memory-mapped I/O registers,
such that reading a register fetches the "next" input value.
On such systems, you don't want the compiler optimizing away
references to the location because it figures the reference
is just going to generate the same value as last time; you
also don't want the compiler introducing new references to the
location figuring that it doesn't need to remember the value
because the value will still be there when it is needed next.

OK, I kept seeing references to embedded systems when I was look at things
regarding this. I assume then that they have more agressively optimising
compilers? Would volatile thus be less useful in a non-embedded system?
To give a concrete example, lets assume the following program is built
in such a way that the variables 'inputs' and 'outputs' are mapped in
the obvious ways to hardware registers.

-------------------------------------------

#define MAKE_IT_WORK ???

#if MAKE_IT_WORK
#define MAGIC volatile
#else
#define MAGIC
#endif

extern unsigned char MAGIC inputs;
extern unsigned char MAGIC outputs;

#define SMOKE_DETECTOR 0x01
#define SPRINKLERS_ON 0x01

int main(void)
{
while (1)
{
if (inputs & SMOKE_DETECTOR)
{
outputs |= SPRINKLERS_ON;
break;
}
}
return 0;
}

-------------------------------------------

If 'inputs' is not declared as volatile, a compiler could relocate
reading its value before the loop, doing it only once (since nothing
changes its value inside the loop)
Similarly if 'outputs' is not volatile, the assignment to it could be
removed altogether, (since it is not used afterwards,) leaving the
equivalent of:

...
int main(void)
{
/* read the value of 'inputs' into a register */
while (1)
{
if ( [saved value of 'inputs'] & SMOKE_DETECTOR)
{
break;
}
}
return 0;
}

--
Roberto Waltman

[ Please reply to the group,
return address is invalid ]
Jul 10 '08 #5
On 2008-07-10, S James S Stapleton <st**********@osu.eduwrote:
Is volatile necessary anymore?
Yes, in portable, standard-conforming C, volatile is a necessary
attribute on a variable that is written by an asynchronous signal handler.
The type volatile sig_atomic_t must be used.
I have a two-thread piece of code I've been
The C language doesn't incorporate a threading API. Threads are described
in various competing extensions to the language, such as POSIX and Win32.
Rules about concurrent access to shared data by multiple threads are
defined by those interfaces.

In POSIX, volatile is not required. Shared data is guarded by the use of
a synchronization object, whose use ensures that the memory is stable.

Volatile is a bad idea because (if implemented earnestly) it interferes
with compiler optimizations, So it would be insane for a threading
platform to require it.

When a thread holds a lock over some shared data, it may make many accesses
and stores to that data. Propagation of data changes from one thread to another
are only necessary on entry to and exit from the critical section. Volatile
goes beyond what is required, asking for more memory traffic than necessary.
The sudocode is at the end.
That's ``pseudocode''.

Sudo is a utility for executing commands with superuser privilege.

So ``sudocode'' is perhaps a script executed by sudo. :)
Jul 10 '08 #6
Thanks, I guess I'm just not sure how my code differs from this in a multi
threaded context. Since another thread may modify the code. Anyway, I'm
continuing this on comp.programming.threading

Thanks for the help.
-Jim Stapleton
Jul 10 '08 #7
In article <g5**********@charm.magnus.acs.ohio-state.edu>
S James S Stapleton <st**********@osu.eduwrote:
>Is volatile necessary anymore? I have a two-thread piece of code ...
The rules for using variables in threads depends on the thread
implementation, so there is no single answer to this question.
(Threads, as others noted, are not standardized in C. Different
thread implementations thus behave differently.)

As a general rule, though, in code that *implements* threads
(rather than simply *using* those provided by some existing
implementation), "volatile" is necessary but not sufficient.
That is, the thread locking code needs to mark certain things
volatile, but *also* needs to prod the compiler in some special
way(s) to get hardware guarantees that are not provided by
the volatile qualifier. (In some specific cases, the hardware
guarantees *are* already provided, and volatile is sufficient.
In some specific compilers, the optimization is weak, and even
the volatile keyword is not required.)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: gmail (figure it out) http://web.torek.net/torek/index.html
Jul 10 '08 #8
S James S Stapleton wrote:
>
Is volatile necessary anymore? I have a two-thread piece of code
I've been testing to figure out what volatile does (fairly simple
code, uses pthreads). I have an update thread (variables passed as
volatile) and a print thread (one variable volatile, the other,
not). There is no difference in the behavior of the volatile and
nonvolatile thread.
.... snip monstrosity ...

First, realize what the 'volatile' characteristic says about an
object. It has nothing to do with threads. It does have to do
with how the object can be modified. For example, the volatile
object could be an integer, which is non-zero when an input port
has unread data, and zero after that data has been read. The
actions which set or reset that flag can be external to the
program. If anything reads the port value, the flag is reset. If
you read the 'ready' status, the flag is unaltered. It can only be
set when the external unit has fresh data. It can only be reset by
reading that data.

Remember that the above is only one illustration of a use for
'volatile'.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.

Jul 10 '08 #9
GPS
Kaz Kylheku wrote:
On 2008-07-10, S James S Stapleton <st**********@osu.eduwrote:
>Is volatile necessary anymore?

Yes, in portable, standard-conforming C, volatile is a necessary
attribute on a variable that is written by an asynchronous signal handler.
The type volatile sig_atomic_t must be used.
>I have a two-thread piece of code I've been

The C language doesn't incorporate a threading API. Threads are described
in various competing extensions to the language, such as POSIX and Win32.
Rules about concurrent access to shared data by multiple threads are
defined by those interfaces.

In POSIX, volatile is not required. Shared data is guarded by the use of
a synchronization object, whose use ensures that the memory is stable.

Volatile is a bad idea because (if implemented earnestly) it interferes
with compiler optimizations, So it would be insane for a threading
platform to require it.
<offtopic>
Some lockless algorithms use volatile. Microsoft's documentation
suggests it for their XBox.

http://msdn.microsoft.com/en-us/libr...95(VS.85).aspx

Some POSIX-based systems use volatile, and the atomic macros for
Linux/BSD sometimes use volatile.

Another thing to keep in mind is that most systems these days do atomic
writes of pointers, and integers, as long as alignment is correct.

The GNU libc for instance depends on this.
http://www.gnu.org/software/libtool/...l#Atomic-Types
When a thread holds a lock over some shared data, it may make many accesses
and stores to that data. Propagation of data changes from one thread to another
are only necessary on entry to and exit from the critical section. Volatile
goes beyond what is required, asking for more memory traffic than necessary.
volatile is not ideal, but it's sometimes required.

Another danger with lock-free algorithms is reordering of writes. So it
requires a lot of care, but sometimes lock-free is the best solution
when lock contention would otherwise reduce performance.

The sooner we can move from the current popular thread models to
Flow-based programming, or the Plan 9 model, or something like those the
better. The current thread models just don't scale with the current
languages to 500 or 1000 cores.
</offtopic>

Jul 11 '08 #10
S James S Stapleton wrote:
>
Is volatile necessary anymore?
[... mega-snip ...]

Yes.

Consider a memory-mapped I/O device:

#define MyIODevice ((volatile char *)0x12345678)
...
void ResetDevice()
{
*MyIODevice = 0x12;
*MyIODevice = 0x34;
}

Without volatile, the compiler can discard the first assignment.

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h|
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:Th*************@gmail.com>

Jul 11 '08 #11

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

14 posts views Thread by Pierre | last post: by
9 posts views Thread by mlimber | last post: by
13 posts views Thread by yaron | last post: by
6 posts views Thread by bwaichu | last post: by
4 posts views Thread by junky_fellow | last post: by
94 posts views Thread by Samuel R. Neff | last post: by
4 posts views Thread by George2 | last post: by
5 posts views Thread by Mark Salsbery [MVP] | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.