c - What is the life-time of asm volatile("" ::: "memory")? -
i have read number of explanations compile barriers , memory barriers, though not sure yet how compiler knows prevention of compile memory ordering starts , ends. (on other hand understand how cpu memory barrier works...)
below arbitrary example, no compile barrier.
int func(int *x, int *y) { int var = 0; x[0] += 1; var += y[0]; y[0] += 1; x[1] += 1; var += y[1]; y[0] += 1; return var; } for example if want prevent compile memory ordering in function, , not in other functions, should insert asm volatile("" ::: "memory") end of function, before returning var?
like:
int func(int *x, int *y) { int var = 0; x[0] += 1; var += y[0]; y[0] += 1; x[1] += 1; var += y[1]; y[0] += 1; asm volatile("" ::: "memory"); return var; }
the barrier prevents reordering (or optimization) wherever put it. there no magical "scope". @ inline assembly instruction:
asm volatile (""::: "memory"); the volatile keyword means put asm statement exactly put it, , don't optimize away (i.e. remove it). after third : list of clobbers, means "i have clobbered memory." telling compiler "i have done affect memory."
in example, have like
y[0] += 1; y[0] += 1; the compiler clever , knows not efficient be. compile like
load y[0] memory register add 2 register store result y[0]
because of pipelining reasons, may more efficient combine other load/modify/store operations. compiler may reorder further merging nearby operations.
to prevent this, can place memory barrier between them:
y[0] += 1; asm volatile (""::: "memory"); y[0] += 1; this tells compiler after first instruction, "i have done memory, may not know it, happened." can not use standard logic , assume adding 1 twice same memory location same adding 2 it, since happened in between. compiled more like
load y[0] memory register add 1 register store result y[0] load y[0] memory register add 1 register store result y[0]
again, possibly reorder things on each side of barrier, not across it.
another example: once, working memory-mapped i/o on microcontroller. compiler saw writing different values same address no read in between, kindly optimized single write of last value. of course, made i/o activity not work expected. placing memory barrier between writes told compiler not this.
Comments
Post a Comment