lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Thu, 5 Apr 2018 10:35:22 -0400 (EDT)
From:   Alan Stern <stern@...land.harvard.edu>
To:     Peter Zijlstra <peterz@...radead.org>
cc:     Daniel Jordan <daniel.m.jordan@...cle.com>,
        <parri.andrea@...il.com>, <will.deacon@....com>,
        <boqun.feng@...il.com>, <npiggin@...il.com>, <dhowells@...hat.com>,
        <j.alglave@....ac.uk>, <luc.maranget@...ia.fr>,
        <paulmck@...ux.vnet.ibm.com>, <akiyks@...il.com>,
        <linux-kernel@...r.kernel.org>,
        Steven Sistare <steven.sistare@...cle.com>,
        Pasha Tatashin <pasha.tatashin@...cle.com>
Subject: Re: Control dependency between prior load in while condition and
 later store?

On Thu, 5 Apr 2018, Peter Zijlstra wrote:

> On Wed, Apr 04, 2018 at 04:35:32PM -0400, Alan Stern wrote:
> > On Wed, 4 Apr 2018, Daniel Jordan wrote:
> > 
> > > A question for memory-barriers.txt aficionados.
> > > 
> > > Is there a control dependency between the prior load of 'a' and the 
> > > later store of 'c'?:
> > > 
> > >    while (READ_ONCE(a));
> > >    WRITE_ONCE(c, 1);
> > 
> > I would say that yes, there is.
> 
> Indeed.
> 
> > Yes, except that a more accurate view of the object code would be
> > something like this:
> > 
> > Loop:	r1 = READ_ONCE(a);
> > 	if (r1)
> > 		goto Loop;
> > 	else
> > 		;	// Do nothing
> > 	WRITE_ONCE(c, 1);
> > 
> > Here you can see that one path branches backward, so everything 
> > following the "if" is dependent on the READ_ONCE.
> 
> Agreed, and I think I even have code that relies on such a pattern
> somewhere.. Ah.. yes, see smp_cond_load_acquire().

One does have to be very careful when talking about compiler behavior.  
This happens to be a particularly delicate point.  My old copy of the
C++11 draft standard says (section 1.10 paragraph 24):


The implementation may assume that any thread will eventually do one of 
the following:

- terminate,
- make a call to a library I/O function,
- access or modify a volatile object, or
- perform a synchronization operation or an atomic operation.

[ Note: This is intended to allow compiler transformations such as 
removal of empty loops, even when termination cannot be proven. - end 
note ]


In this example, READ_ONCE() is in fact a volatile access, so we're 
okay.  But if it weren't, the compiler might decide to assume the loop 
will eventually terminate, meaning that the WRITE_ONCE() would always 
be executed eventually.  Then there would be nothing to prevent the 
compiler from moving the WRITE_ONCE() up before the start of the loop, 
which would of course destroy the control dependency.

Alan

Powered by blists - more mailing lists