c++ - Constant folding/propagation optimization with memory barriers -
i have been reading while in order understand better whats going on when multithread programming modern (multicore) cpu. however, while reading this, noticed code below in "explicit compiler barriers" section, not use volatile ispublished
global.
#define compiler_barrier() asm volatile("" ::: "memory") int value; int ispublished = 0; void sendvalue(int x) { value = x; compiler_barrier(); // prevent reordering of stores ispublished = 1; } int tryrecvvalue() { if (ispublished) { compiler_barrier(); // prevent reordering of loads return value; } return -1; // or other value mean not yet received }
the question is, safe omit volatile ispublished
here? many people mention "volatile" keyword has nothing multithread programming , agree them. however, during compiler optimizations "constant folding/propagation" can applied , wiki page shows possible change if (ispublished)
if (false)
if compiler not knows can change value of ispublished
. miss or misunderstood here?
memory barriers can prevent compiler ordering , out-of-order execution cpu, said in previos paragraph still need volatile
in order avoid "constant folding/propagation" dangereous optimization using globals flags in lock-free code?
if tryrecvvalue()
called once, safe omit volatile ispublished
. same true in case, when between calls tryrecvvalue()
there function call, compiler cannot prove, not change false value of ispublished
.
// example 1(safe) int v = tryrecvvalue(); if(v == -1) exit(1); // example 2(unsafe): tryrecvvalue may inlined , 'ispublished' may not re-read between iterations. int v; while(true) { v = tryrecvvalue(); if(v != -1) break; } // example 3(safe) int v; while(true) { v = tryrecvvalue(); if(v != -1) break; some_extern_call(); // possibly can change 'ispublished' }
constant propagation can applied when compiler can prove value of variable. because ispublished
declared non-constant, value can proven if:
- variable assigned given value or read variable followed branch, executed in case when variable has given value.
variable read (again) in same program's thread.
between 2 , 3 variable not changed within given program's thread.
unless call tryrecvvalue()
in sort of .init function, compiler never see ispublished initialization in same thread reading. so, proving false value of variable according initialization not possible.
proving false value of ispublished according false (empty) branch in tryrecvvalue
function possible, see example 2
in code above.
Comments
Post a Comment