Topic: accidental modifications
Author: "Sergey P. Derevyago" <non-existent@iobox.com>
Date: Sat, 30 Dec 2000 14:06:58 GMT Raw View
Here is the part of a post from comp.programming.threads:
-----------------------------------8<-----------------------------------
Subject: Re: Registers and shared memory
Date: Thu, 28 Dec 2000 07:03:29 -0500
From: Dave Butenhof <David.Butenhof@compaq.com>
Organization: Compaq Computer Corporation
Newsgroups: comp.programming.threads
References: <aOn26.30499$Es2.774423@zwoll1.home.nl>
[snip]
Operations on a char, or even a long, may or may not be atomic. You
don't know, you can't control the code generated by the compiler, and
you shouldn't usually care.
In this particular case, you need to worry about word tearing. In
principle, you could say that the mutexes are really associated with the
individual elements of the array, rather than with a CPU, so that m[0]
controls access to x[0] and m[1] controls access to x[1], regardless of
which thread is doing the accessing. However, separating closely aligned
data into separate locks is always risky. The hardware may not have byte
fetch/store instructions; and even if it does, it need not choose to use
them in this case. It may decide that it's better/faster to fetch a
short, int, or long containing the char you want, mask it out, replace
the original char with the new value, and store it back where it came
from. If both threads do this simultaneously on adjacent chars, one may
overwrite the other even though both were "properly" locked.
[snip]
-----------------------------------8<-----------------------------------
Is it a standard conforming behavior to modify adjacent memory "under the
corners"? How can such behavior be prevented within standard C++?
--
With all respect, Sergey. http://cpp3.virtualave.net/
mailto : ders at skeptik.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: Greg Jaxon <gpjaxon@home.com>
Date: Tue, 2 Jan 2001 20:50:42 GMT Raw View
"Sergey P. Derevyago" wrote:
>
> Here is the part of a post from comp.programming.threads:
> -----------------------------------8<-----------------------------------
> Subject: Re: Registers and shared memory
> Date: Thu, 28 Dec 2000 07:03:29 -0500
> From: Dave Butenhof <David.Butenhof@compaq.com>
> Organization: Compaq Computer Corporation
> Newsgroups: comp.programming.threads
> Operations on a char, or even a long, may or may not be atomic. You
> don't know, you can't control the code generated by the compiler, and
> you shouldn't usually care.
> In this particular case, you need to worry about word tearing.
> [...] separating closely aligned data into separate locks is always risky.
> The hardware may not have byte fetch/store instructions; and even if it does,
> it need not choose to use them in this case. It may decide that it's
> better/faster to fetch a short, int, or long containing the char you want,
> mask it out, replace the original char with the new value, and store it back
> where it came from. If both threads do this simultaneously on adjacent chars, one may
> overwrite the other even though both were "properly" locked.
> -----------------------------------8<-----------------------------------
> Is it a standard conforming behavior to modify adjacent memory "under the
> corners"? How can such behavior be prevented within standard C++?
> --
> With all respect, Sergey. http://cpp3.virtualave.net/
> mailto : ders at skeptik.net
Fetching a longer value, masking in a change, and then storing back the longer
value does not "modify" any adjacent memory within the single-threaded execution
model of the C++ standard. The C++ standard model would be satisfied even if each
action fetched and rewrote all of memory! There are many ways in which the standard
ignores the basic needs of parallel programmers. For example, it doesn't define how
a shared object must be constructed only once and fully constructed before any
concurrent uses proceed; nor does it provide for object destruction before exec()
is called. Parallel programming is not standardized by ISO for C++.
A few hardware vendors have tried to blend byte-addressing with word-atomicity; they
ask their compiler people to work a minor miracle, and the results usually disappoint
either in speed or correctness.
These issues all fall into a series of questions about the "quality of implementation"
of your hardware, compiler, library software and their interactions. The general
term for this is "thread-safety". Each thread-safe component agrees to handle certain
aspects of the parallel programming effort, and altogether they have to cover all
of the bases so that there are no timing holes, or accidental deadlocks implicit in
the pthread actions themselves. The few compilers for multiprocessors that handle
these issues use special compiler options such as "-mt", "-pthread", or "--thread_safe"
to restrict their code generation to the tighter rules appropriate for the target
hardware and to interaction with the pthread libraries.
The pthread interface is not especially Object Oriented, or C++ friendly. Certain
features of it (asynchronous thread cancellation in particular) completely kill
almost all interesting code optimizations. And there is an inherent philosophical
mismatch between data abstraction and some of the contracts needed to maintain thread
safety. Recall that a typical rule for deadlock-free use of mutexes is that there
must be a partial ordering of all mutexes so that while holding mutex A one can only
acquire mutexes lower than A in the ordering. This means that an object implementation
must never conceal which mutexes it uses to get its job done -- or the partial ordering
of those mutexes imposed by its algorithms.
Good designs for parallel processing date to the early 1960s. But the commercial
advantage of ignoring user-accessible parallelism has been overwhelming.
Parallel mainframe vendors were killed by uniprocessed RISC workstations.
SMP RISC has been flattened by Pentium chips.
Now Pentium III and 4s are ready for multiprocessing, and Intel stock is
no longer doubling every time you blink.
I'm afraid it will never be economical to make a great parallel programming environment
unless it forms a natural evolution from the uniprocessor world.
And high-performance uniprocessing is a difficult starting point for the design of a
multiprocessing system.
Greg Jaxon
Burroughs B6/7000 APL&Algol;
Alliant FX-8s, CSRD Cedar Machine;
KAI F90&C++ compilers;
... (what next?)
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: James Dennett <james@evtechnology.com>
Date: Tue, 2 Jan 2001 20:52:30 GMT Raw View
"Sergey P. Derevyago" wrote:
>
> Here is the part of a post from comp.programming.threads:
> -----------------------------------8<-----------------------------------
> Subject: Re: Registers and shared memory
> Date: Thu, 28 Dec 2000 07:03:29 -0500
> From: Dave Butenhof <David.Butenhof@compaq.com>
> Organization: Compaq Computer Corporation
> Newsgroups: comp.programming.threads
> References: <aOn26.30499$Es2.774423@zwoll1.home.nl>
>
> [snip]
>
> Operations on a char, or even a long, may or may not be atomic. You
> don't know, you can't control the code generated by the compiler, and
> you shouldn't usually care.
>
> In this particular case, you need to worry about word tearing. In
> principle, you could say that the mutexes are really associated with the
> individual elements of the array, rather than with a CPU, so that m[0]
> controls access to x[0] and m[1] controls access to x[1], regardless of
> which thread is doing the accessing. However, separating closely aligned
> data into separate locks is always risky. The hardware may not have byte
> fetch/store instructions; and even if it does, it need not choose to use
> them in this case. It may decide that it's better/faster to fetch a
> short, int, or long containing the char you want, mask it out, replace
> the original char with the new value, and store it back where it came
> from. If both threads do this simultaneously on adjacent chars, one may
> overwrite the other even though both were "properly" locked.
>
> [snip]
>
> -----------------------------------8<-----------------------------------
> Is it a standard conforming behavior to modify adjacent memory "under the
> corners"?
The C++ Standard does not address issues of multi-threading at all,
so theoretically at least this could be a problem. A good compiler
would document its policy on this, and you might be able to work
around a quirky compiler at the loss of some efficiency by using the
volatile qualifier.
> How can such behavior be prevented within standard C++?
Easy ;) Within Standard C++, you can have only a single thread, so
the problem does not arise.
I do not know if there are any plans to address multi-threading in a
future version of the C++ Standard. I would hope so; most of the C++
code I have written is multi-threaded, and I would like to be assured
(at least) that the Standard Library is portably usable in a careful
multi-threaded program.
-- James Dennett <jdennett@acm.org>
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: Michiel Salters <salters@lucent.com>
Date: Tue, 2 Jan 2001 21:02:18 GMT Raw View
"Sergey P. Derevyago" wrote:
> Here is the part of a post from comp.programming.threads:
> -----------------------------------8<-----------------------------------
> Subject: Re: Registers and shared memory
> From: Dave Butenhof <David.Butenhof@compaq.com>
> Newsgroups: comp.programming.threads
[snip]
> Operations on a char, or even a long, may or may not be atomic. You
> don't know, you can't control the code generated by the compiler, and
> you shouldn't usually care.
> In this particular case, you need to worry about word tearing. In
> principle, you could say that the mutexes are really associated with the
> individual elements of the array, rather than with a CPU, so that m[0]
> controls access to x[0] and m[1] controls access to x[1], regardless of
> which thread is doing the accessing. However, separating closely aligned
> data into separate locks is always risky. The hardware may not have byte
> fetch/store instructions; and even if it does, it need not choose to use
> them in this case. It may decide that it's better/faster to fetch a
> short, int, or long containing the char you want, mask it out, replace
> the original char with the new value, and store it back where it came
> from. If both threads do this simultaneously on adjacent chars, one may
> overwrite the other even though both were "properly" locked.
[snip]
> -----------------------------------8<-----------------------------------
> Is it a standard conforming behavior to modify adjacent
> memory "under the corners"? How can such behavior be prevented
> within standard C++?
C++ as defined by the standard has no threads. Ok, one, the thread started
by main. Reads from chars therefore will never be interrupted by other
writes, which prevents the problem above from occurring.
IMO a C++ compiler which -as an extension- supports threads should support
them in such a way that the problem above does not occur, but that is
only QOI. There is no formal document that binds them.
The way to prevent it is to start an organization which produces a new
standard document, this would define the interaction between threads and
C++. Something like POSIX threads, but from what I hear there isn't
a lot of enthousiasm in the POSIX community for C++ bindings for threads
(only). Compiler vendors could then (optionally) claim conformance with
that standard.
Regards,
--
Michiel Salters
Michiel.Salters@cmg.nl
salters@lucent.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]