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 > sequence > > 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 implementation-defined. 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 details. > > 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 > trylock() > { > int res; > > res = pthread_mutex_trylock(&mutex); > if (res == 0) > ++acquires_count; > > 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 > generates: > > trylock: > 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 > leave > ret > 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.> Erik Trulsson [EMAIL PROTECTED]