Subj : Re: 'volatile' Rules To : comp.programming.threads From : Uenal Mutlu Date : Tue Jun 07 2005 03:49 pm "Uenal Mutlu" wrote > 'volatile' Rules in C/C++ MT programs: > -------------------------------------- > > Facts about 'volatile': > f1) volatile disables optimizations for the given variable. > f2) some measurements show that its use leads to about 35% and more performance penalty. > > Below I've tried to formulate a rule for when safely not to use volatile > for getting max performance and still be on the safe side. > > Rule: volatile is not necessary if (a OR (b AND c AND d) holds: > a) variable is used in a locked state (ie. protected via mutex etc.). > b) size of variable <= machine word. > c) variable is aligned on machine word boundary > (ie. its start adress is an integral multiple of machine word size). > d) within the same func there is at least 1 "funccall" before > subsequent queries to, or modifications of, the variable. UPDATE: Some experimentations show that the second method ("b and c and d") is by no means reliable. It _seems_ to work only if there is no function call between the visits to the variable, or if the called functions are all inlined (--> ie. rule d seems to be wrong). The consequence is: only the use of locking gives a safe method, everything else is unreliable and very risky. > Regarding d: > Clear: > c1) calling an operator for a primitive type is NOT a "funccall". > > Unclear yet (in this context): > u1) is calling an inline func a "funccall"? [yes] > u2) is calling an operator for a non-primitive type a "funccall"? [yes] > > > Reference citations from a discussion in comp.lang.c++.moderated > (thread "passing data between threads"): > > rc1) [...] Posix defines the semantics of C with regards to threading in such a way > that a compiler cannot maintain variables accessible from another thread > in registers across calls to a certain number of functions, including all > functions which acquire a lock. If the compiler is Posix conform, > volatile isn't necessary [...] > (James Kanze) > > rc2) [...] Locking mutexes (and misleadigly named critical sections) impose a memory > barrier and is a function call. A compiler can not assume state of variables > after a function call, so it rereads them from memory no matter if they > are declared volatile or not. So, you don't need volatile in this case [...] > (Maxim Yegorushkin) > > rc3) [...] The point is that when you do the locking (or any other operation that > guarantees visibility of changes), then, well, the changes are > guaranteed to be visible. You don't need to do any further tricks. > Remember that in order to write programs compliant with some MT standard > (like POSIX), then everything you use needs to be aware of this standard > - not only the OS, but also the compiler, run-time library, everything. > This means that the compiler cannot optimize accesses across locking > operations. Either it is dumb enough not to optimize across any function > call or it is smart enough to recognize that what you are doing is a > sychronization operation with some guarantees that cannot be bypassed. > So, you don't need to do anything to ensure that the variable will be > re-read after entering the locked region [...] > (Maciej Sobczak) .