Re: Thread question
- From: Rainer Weikusat <rainer.weikusat@xxxxxxxxx>
- Date: Wed, 31 Jan 2007 12:56:12 +0100
"David Schwartz" <davids@xxxxxxxxxxxxx> writes:
On Jan 31, 2:18 am, Rainer Weikusat <rainer.weiku...@xxxxxxxxx> wrote:
Your second sentence does not support the first, which should have
been 'this is an incompletely specified requirement'. And even this is
untrue, because 'everything that is going to happen as part of the
write access has completed' is a complete specification, because
'everything' means everything [that could possibly be noticed by a
conforming program].
Since a conforming program can only have one thread, what does this
argument get you?
It demonstrates that you didn't know what a 'conforming program' is
(according to ISO-C). This is defined in 4|7 as:
A conforming program is one that is acceptable to a conforming
implementation.
Reading the standard this way would be a disaster for programs that
use 'volatile' correctly. Why should a single-threaded program that
calls 'longjmp' incur the penalty of full commitment on each write?
Why should something which only makes sense for multithreaded programs
need to take place in single-threaded programs as well?
Because the compiler generally can't tell at compile time how many
threads a program will have at run time.
'How many' isn't interesting. There are two possibilites here: Exactly
one thread. More than one thread. This information could be made
available to the compiler in a number of ways.
Even if it could, multithreaded programs still use 'volatile' for
its intended purpose, in code that deals with signals and longjmp.
Insofar C is concerned, access to a volatile object is considered to
be a side effect with all the requirements I was talking about, while
for a non-volatile object, only modifing the object is.
I wasn't talking about 'extending the standard' but about 'maintaining
the standardized semantics', aka 'extending [the semantics] to
environments containing things not in the C-standard'.
This is a disaster for proper users of 'volatile' who pay the penalty
of thread synchronization even though they don't need it.
'Proper users of volatile' are those who use it to ensure that read
accesses are side-effects as well, meaning all of them are supposed
to happen, while the compiler is otherwise free to, eg, re-used
unchanged values found in registers. Assuming the the ISO-C
requirements regarding side effects and sequence points extend to
multi-threaded programs (instead of becoming meaningless in
multi-threaded programs) would most likely mean some performance
penalty for accesses to potentially shared objects and this is the
exact reason why the 'usual' assumption is that they may be ignored.
Similar issues arise for CPUs that do write-reordering even for the
single-threaded case, because the end of a statement is a sequence
point in C (among other things), meaning, there must not be any
interstatement write reordering, ie there would need to be an implicit
memory barrier after each statement (or any other sequence point,
fwiw).
There is *no* counterbalancing benefit. Every sane threads platform
provides more sophisticated thread synchronization primitives with
precisely defined semantics and less overhead than a variable
modifier could ever have.
The second claim cannot possibly be true, because 'thread
synchronization' isn't magic, and so both would need to use the same
'primitves' for implementation.
[...]
At some point in the past, the simpler requirements of the C-standard
did this, too. Which leads to the interesting question how long it
will take for CPU-makers to ignore the present requirements for the
sake of performance as well.
When you had a single CPU, no caches, and main memory, it was quite
clear what it meant for a write to main memory to complete. It was
also clear what it meant for a change to a variable to be "observable"
since there was only one place to observe it. However, with posting
buffers, caches, and the life, the idea of "observing" a change to
memory is simply no longer coherent.
This hasn't become more true since the last iteration. 'Oberservable'
means 'observable', not restrictions imposed. Consequently
_everything_ (still meaning 'everything') that may be necessary to
prevent something different to 'observe' a difference must have been
completed. This would include flushing any intermediate buffers insofar
code could observe the difference. Of course, a lot of lot of
performance enhancing mechanisms in current CPUs/ systems would be
rendered mostly or totally ineffective by this. But that something may
be a bad idea is independent of its eventual standarization status in
arbitrary standards.
.
- Follow-Ups:
- Re: Thread question
- From: Gil Hamilton
- Re: Thread question
- References:
- Re: Thread question
- From: Paul Pluzhnikov
- Re: Thread question
- From: Mihai Osian
- Re: Thread question
- From: Paul Pluzhnikov
- Re: Thread question
- From: Mihai Osian
- Re: Thread question
- From: David Schwartz
- Re: Thread question
- From: Mihai Osian
- Re: Thread question
- From: David Schwartz
- Re: Thread question
- From: Rainer Weikusat
- Re: Thread question
- From: David Schwartz
- Re: Thread question
- From: Rainer Weikusat
- Re: Thread question
- From: David Schwartz
- Re: Thread question
- From: Rainer Weikusat
- Re: Thread question
- From: David Schwartz
- Re: Thread question
- Prev by Date: Re: Thread question
- Next by Date: Re: Thread question
- Previous by thread: Re: Thread question
- Next by thread: Re: Thread question
- Index(es):
Relevant Pages
|