This is the mail archive of the
mailing list for the GCC project.
Re: Optimization of conditional access to globals: thread-unsafe?
On Mon, Oct 22, 2007 at 01:36:17PM +0400, Tomash Brechko wrote:
> On Mon, Oct 22, 2007 at 00:07:50 +0100, Dave Korn wrote:
> > Because of the 'as-if' rule. Since the standard is neutral with regard to
> > threads, gcc does not have to take them into account when it decides whether
> > an optimisation would satisfy the 'as-if' rule.
> If this would be true, then the compiler is free to inject the
> mov mem -> reg
> mov reg -> mem
> just _anywhere_.
As far as the C standard is concerned, yes, the compiler is most certainly
free to insert such a sequence almost anywhere.
If a variable has been declared as 'volatile' however, then all accesses to
it must be according to the abstract machine defined by the C standard, i.e.
the compiler is not allowed to optimize away any access to the variable, nor
is it allowed to insert spurious accesses to the variable.
It is worth noting that exactly what constitutes an access is
It is also worth noting that just declaring a variable 'volatile' does not
help all that much in making it safer to use in a threded environment if you
have multiple CPUs. (There is nothing that says that a multi-CPU system has
to have any kind of automatic cache-coherence.)
> How the programmer can predict where and when to
> lock the mutex to protect mem? The only thing we could relay on then
> is that the compiler is sound, it wouldn't inject such a sequence
> unless it really feels so. But still, how to determine when the
> compiler really feels so?
You will have to read the documentation for the compiler and the
threading library caerfully, and hope that they have something useful
to say on this matter. All too often they won't, in which case
you will have to do what most programmars do in practice in this situation:
Write something that "should" work, and hope for the best. Most of the time
it will actually work.
My own conclusion from this discussion (and others) is that shared memory is
a lousy paradigm for communication between different threads of execution,
precisely because it is so hard to specify exactly what should happen or not
happen in various situations. (Most of the time the relevant standards
do not actually specify this in sufficient detail.) I also conclude that
POSIX threads should be avoided if you are really concerned about
correctness. (Which of course hasn't stopped lots of people from using
them - with varying results.)
Message passing has an advantage here since then only the people writing
the actual message-passing routines need to know about the underlying
> Here's another piece of code, more real and sound this time:
> #include <pthread.h>
> static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
> static int acquires_count = 0;
> int res;
> res = pthread_mutex_trylock(&mutex);
> if (res == 0)
> return res;
> Is it thread safe? Or rather, should the compiler preserve its
> thread-safeness, as seen from the programmer's POV? Otherwise I don't
> get how pthread_mutex_trylock() could possibly ever be used, because
> it's exactly the case when you _have_ to do the access based on the
> condition, "assume the worst" won't work here. GCC 4.3 with -O1
> pushl %ebp
> movl %esp, %ebp
> subl $8, %esp
> movl $mutex, (%esp)
> call pthread_mutex_trylock
> cmpl $1, %eax ; test res
> movl acquires_count, %edx ; load
> adcl $0, %edx ; maybe add 1
> movl %edx, acquires_count ; store
What happens if you declare the variables as 'volatile' ?
(There is no guarantee that this will make things better, but it
is very likely.)
<Insert your favourite quote here.>