Subj : Re: double-checked locking in C To : comp.programming.threads From : Laurent Deniau Date : Thu Jul 07 2005 09:42 pm David Hopwood wrote: > Laurent Deniau wrote: > >> David Schwartz wrote: >> >>> "Laurent Deniau" wrote: >>> >>>> Now, there is the problem of reflecting the change of the side >>>> effects to other threads. My suggestion was to put the flag inside >>>> the side object itself. Therefore if the init_value is seen, the >>>> object is also seen. Of course you may think that the object takes >>>> place on cache line boundary and is only partially updated. That is >>>> in the worst case, only the flag part and not the rest. But I am not >>>> sure if this can happen. >>> >>> >>> You just don't get it. We're talking about *PORTABLE* code >>> written for an abstract machine. There is no such thing as a cache line. >> >> >> Right, I was try to examine how it could fail. >> >>> You have the guarantees the standards give you. And that's it. If >>> you claim anything else is guaranteed, then you have code that's >>> *not* portable. >> >> >> Then if I stick to standards, the C norm is enough (6.7.3-6 which says >> all and nothing) and I just have to use volatile. > > > Standard C90/99 doesn't define the behaviour of multithreaded code, Right. > whether > volatile is used or not. It ensures that side effects are updated at sequence point and no other side effects is started, whatever "side effects" means (implementation defined). I agree that *in practice* it is not effective on modern architectures despite of what it says. That is why talking about the C99 norm for this topic is not realistic here. If implementation wanted to follow the C99 norm it would have to implement volatile with the same semantic as in Java (it was the case before the introduction of cache), which would not be efficiency-compatible with C89 code. > POSIX explicitly says that the behaviour of your > example code is undefined: > > > # 4.10 Memory Synchronization > # > # Applications shall ensure that access to any memory location by more > # than one thread of control (threads or processes) is restricted such > # that no thread of control can read or modify a memory location while > # another thread of control may be modifying it. Such access is restricted > # using functions that synchronize thread execution and also synchronize > # memory with respect to other threads. Ok. >> At the sequence points, the value is correct even if modified by side >> effects. But as you know, it doesn't solve anything because of the >> presence of caches on processors, something absent from the norm and >> very uncommon at the time volatile was invented. > > > It has nothing to do with the presence of caches. Your code can fail in > practice because of reordering of memory accesses -- both processor > reordering, and compiler reordering if whole-program optimization is done. Volatile forbids reordering so reodering is not an issue. Visibility is one since it does not exist in the C norm. ld. .