This is the mail archive of the
mailing list for the GCC project.
Re: Optimization of conditional access to globals: thread-unsafe?
- From: "Bart Van Assche" <bart dot vanassche at gmail dot com>
- To: "Andrew Haley" <aph-gcc at littlepinkcloud dot com>
- Cc: gcc at gcc dot gnu dot org, "Andrew Pinski" <pinskia at gmail dot com>, "Tomash Brechko" <tomash dot brechko at gmail dot com>
- Date: Fri, 26 Oct 2007 16:05:17 +0200
- Subject: Re: Optimization of conditional access to globals: thread-unsafe?
- References: <firstname.lastname@example.org>
On 10/22/07, Andrew Haley <aph-gcc at littlepinkcloud dot COM> wrote:
> The core problem here seems to be that the "C with threads" memory
> model isn't sufficiently well-defined to make a determination
> possible. You're assuming that you have no responsibility to mark
> shared memory protected by a mutex as volatile, but I know of nothing
> in the C standard that makes such a guarantee. A prudent programmer
> will make conservative assumptions.
I agree that according to the C and C++ language standards, any
variable shared over threads should be declared volatile. But it is
nearly impossible to live with this requirement: this requirement
implies that for each library function that modifies data through
pointers a second version should be added that accepts a volatile
pointer instead of a regular pointer. Consider e.g. the function
snprintf(), which writes to the character buffer passed as its first
argument. When snprintf() is used to write to a buffer that is not
shared over threads, the existing snprintf() function is fine. When
however snprintf() is used to write to a buffer that is shared by two
or more threads, a version is needed of snprintf() that accepts
volatile char* as its first argument.
My opinion is that it should be possible to declare whether C/C++ code
has acquire, release or acquire+release semantics. The fact that code
has acquire semantics means that no subsequent load or store
operations may be moved in front of that code, and the fact that code
has release semantics means that no preceding load or store operations
may be moved past that code. Adding definitions for acquire and
release semantics in pthread.h would help a lot. E.g.
pthread_mutex_lock() should be declared to have acquire semantics, and
pthread_mutex_unlock() should be declared to have release semantics.
Maybe it is a good idea to add the following function attributes in
gcc: __attribute__((acquire)) and __attribute__((release)) ? A
refinement of these attributes would be to allow to specify not only
the acquire/release attributes, but also the memory locations to which
the acquire and release apply (pthreads synchronization functions
always apply to all memory locations).
I'm not inventing anything new here -- as far as I know the concepts
of acquire and release were first defined by Gharachorloo e.a. in 1990
(Memory consistency and event ordering in scalable shared-memory
multiprocessors, International Symposium on Computer Architecture,
Bart Van Assche.