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

Popular posts from this blog

routing - AngularJS State management ->load multiple states in one page -

python - GRASS parser() error -

Swift game error message -