Path: csiph.com!usenet.pasdenom.info!gegeweb.org!eternal-september.org!feeder.eternal-september.org!mx04.eternal-september.org!.POSTED!not-for-mail From: Uncle Steve Newsgroups: comp.lang.c Subject: Re: Clarification on the applicability of compile-time optimization to a struct variable which encompasses a mixture of fields declared as volatile and non-volatile individually Date: Fri, 06 Jul 2012 14:01:01 -0400 Organization: A noiseless patient Spider Lines: 131 Message-ID: <7ee0b658ce2dc96-3111f@gmail.com> References: <94eafd27-6aba-4a17-9403-d42912312e6c@googlegroups.com> <0.8f83cddfeac55b9f2de1.20120705232249BST.87k3yhalvq.fsf@bsb.me.uk> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 8bit Injection-Info: mx04.eternal-september.org; posting-host="M1JqkNNJU2aX/HiSUuiK1A"; logging-data="24669"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+OWw/OBk+bni750DY0Rstd" User-Agent: nn 6.7.3 Content-Length: 3458 Cancel-Lock: sha1:GFVGL/5yE5e82SQXSs3oElka9rY= Xref: csiph.com comp.lang.c:23112 On Sat, Jul 07, 2012 at 09:20:57AM +1200, Ian Collins wrote: > On 07/ 7/12 05:08 AM, Uncle Steve wrote: > >On Thu, Jul 05, 2012 at 11:22:49PM +0100, Ben Bacarisse wrote: > >> > >>To a very large extent, the C standard washes it hands of volatile > >>objects. Sure, it says a fair bit about what *may* happen but it also > >>says "[w]hat constitutes an access to an object that has volatile- > >>qualified type is implementation-defined" (6.7.3 p7) and "[a]n actual > >>implementation need not evaluate part of an expression if it can deduce > >>that [...] no needed side effects are produced (including any caused by > >>[...] accessing a volatile object)" (5.1.2.3 p4). > >> > >>Together, these give an implementation so much leeway that you often > >>need to refer to the implementation, not the standard. For example, an > >>implementation may well be able to deduce that the assignment is not a > >>"needed side effect", coming as it does at the start of main. Equally, > >>an implementation may treat all accesses to volatile-qualified objects > >>with kid gloves. > > > >This is a concern in my mind right now as I'm writing some posix > >threads code, and so obviously there are a large number of variables > >which ought to be declared volatile. > > What leads you to that conclusion? That line of though usually implies > you are misunderstanding the relationship between volatile and threads. > > What are you trying to achieve with volatile? Well, I have some data structures that will be accessed from arbitrary threads, so I want to make sure there's no funny business happening behind the scenes where the compiler decides that certain accesses are optional. Here's a little snippet of code which shows the issue, albeit without nested structures: #include struct sample_s { T64 a, b; }; typedef struct sample_s sample; #define SAMPLES 100 #define nsclock(p) { \ volatile struct timespec T; \ clock_gettime(CLOCK_MONOTONIC, &T); \ p = T.tv_sec * 1000000000 + T.tv_nsec; \ } void do_timing(sample * p) { volatile T64 s, e, v; // volatile unsigned int i; nsclock(s); nsclock(s); // for(i = 0; i < 1 ; i++); nsclock(e); p->a = (e - s); nsclock(e); p->b = (e - s); return; } void emit_sample(sample *p) { fprintf(stdout, "%-5d %-5d %-5d\n", p->a, p->b, p->b - p->a); return; } int main(char *argv, int argc) { sample tr[SAMPLES + 1]; int i; tr[SAMPLES].a = tr[SAMPLES].b = 0; for(i = 0; i < SAMPLES; i++) do_timing(&tr[i]); fprintf(stdout, "Timing results for %d samples:\n\n", SAMPLES); fprintf(stdout, "%-5s %-5s %-5s\n", "A", "B", "B - A"); for(i = 0; i < SAMPLES; i++) emit_sample(&tr[i]); exit(0); } So, without including all the crap in local_time.h, I have to explain a few definitions. T64 is an unsigned long long int representing microseconds since epoch, but I ended up using it as if it represented nanoseconds since epoch since my i3 dual core laptop has a nanosecond-resolution timer. The variable declared volatile are required otherwise some variable accesses are optimized out, giving inaccurate results during the data acquisition phase. The problems here are magnified when these access patterns occur with competing threads. IIRC, mutexes are not memory access barriers and solve different problems. Regards, Uncle Steve -- The moon has never been closer.