On 2 май, 14:43, Anthony Williams <anthony_w....@[EMAIL PROTECTED]
> wrote:
> Dmitriy Vyukov <dvyu...@[EMAIL PROTECTED]
> writes:
> > Will it be possible to issue only compiler ordering barrier (release,
> > acquire or full), but not hardware ordering barrier in C++0x?
>
> > Accesses to volatile variables are ordered only with respect to
> > accesses to other volatile variables. What I want it to order access
> > to variable with respect to accesses to all other volatile and non-
> > volatile variables (w/o any hardware barriers, only compiler
> > ordering).
>
> Within a single thread, all operations *are* ordered. The ordering
relations
> are happens-before and sequenced-before. A is sequenced-before before B
when
> A physically comes before B in the source code, or the sequencing rules
say so
> (e.g. lhs of a comma op is sequenced before rhs).
>
> If A is sequenced-before B, then A also happens-before B. If you then
> introduce a synchronization edge between thread T1 and thread T2
> (e.g. store(mem_order_release) on T1, load(mem_order_acquire) on T2),
then
> anything that happens-before the store also happens-before the load.
>
> > Such compiler barriers are useful in effective synchronization
> > algorithms like SMR+RCU:
> >http://sourceforge.net/project/showfiles.php?group_id=127837
> > (fastsmr package)
> > because they allows one to eliminate all hardware memory barriers from
> > fast-path.
>
> All accesses to shared data MUST be synchronized with atomics: if there
are
> two accesses to a non-atomic variable, at least one of which is a write,
and
> there is NOT a happens-before relation between them, you have a data
race, and
> undefined behaviour.
>
> If you can prove that you have a happens-before relation, you're safe,
> otherwise you need to do some synchronization, or perhaps use
> mem_order_relaxed.
I can prove that I have happens-before relation if I can enforce
correct compiler ordering. Consider following code:
std::vector<int> g_nonatomic_user_data;
std::atomic_int g_atomic1;
std::atomic_int g_atomic2;
std::vector<int> thread()
{
g_atomic1.store(1, std::memory_order_relaxed);
// compiler store-load fence
if (g_atomic2.load(std::memory_order_relaxed))
{
g_atomic1.store(0, std::memory_order_relaxed);
return std::vector<int>();
}
// compiler acquire fence
std::vector<int> local = g_nonatomic_user_data;
// compiler release fence
g_atomic1.store(0, std::memory_order_relaxed);
return local;
}
It's a kind of Peterson's algorithm *but* w/o store-load memory
barrier, and w/o acquire and release barriers. The point is that I
still can prove happens-before relation wrt accesses to
g_nonatomic_user_data, if I can enforce mentioned compiler barriers.
Basically I need to ensure that accesses to g_nonatomic_user_data will
not hoist above or sink below accesses to g_atomic1 in generated
machine code.
Now I can do this with _ReadWriteBarrier (msvc) or "__asm__
__volatile__ ("" : : :"memory")" (gcc).
Dmitriy V'jukov
--
[ See http://www.gotw.ca/resources/clcm.htm
for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


|