[cpp-threads] D2335 (sequential consistency proof) revision
Lawrence Crowl
Lawrence at Crowl.org
Fri Aug 24 19:18:23 BST 2007
Boehm, Hans <hans.boehm at hp.com> wrote:
> Consider the following (variant of a well-known) example, where x is
> atomic (initially zero, SC ops only) and l1 is initially unlocked:
>
> Thread 1:
> x.store(1);
> l1.lock();
>
> Thread 2:
> r2 = trylock(); // fails
> r3 = x.load(); // yields 0
>
> Note that lock and trylock are both only acquire operations,
> even though the trylock reads the value written by the lock.
>
> Since there are no synchronizes-with relationships and hence no
> happens-before relationships across threads, the current plan is
> to insist on a total order only among SC atomics, not locks,
Herb Sutter <hsutter at microsoft.com> wrote:
> I didn't realize that. I don't agree, because atomics and locks
> (and, sigh, fences) should be interchangeable for synchronization
> purposes. They all express (parts of) critical sections, and we
> shouldn't have multiple types of critical sections that have odd
> interactions. Besides, then programs wouldn't be SC, right? And
> I thought the goal of having SC atomics (esp. as the default) was
> so that programs that use just locks (correctly, meaning not the
> trylock trick) and SC atomics are SC.
More importantly, one needs to be able to replace locks in the
implementation a library with atomics and still retain sequentially
consistency with clients.
Lawrence Crowl <Lawrence at crowl.org> wrote:
> That is, without decoration [locks] are SC, not just acquire
> or release.
Herb Sutter <hsutter at microsoft.com> wrote:
> Why should taking a lock be a full fence? The only use case I know
> of for making a lock operation a full fence is the anti-idiom of
> abusing a trylock or timed lock to detect a lock taken by another
> thread, as Hans noted below.
>
> I thought that taking a lock enters a critical section, which only
> needs to be an acquire.
The reasoning is that if SC is a strong goal, then we need to provide
the mechanisms to make it achievable. An alternate approach is to
disallow this use of the trylock.
Paraphrasing Boehm, Hans <hans.boehm at hp.com>:
> Option 1: Race free defined via "simultaneous execution of
> conflicting actions". Successful lock has release semantics.
> Option 2: Race free defined via happens-before. Successful trylock
> has acquire semantics.
> Option 3: Leave the current version alone and accepting that
> trylock/timedlock get you out of the SC domain, unless you follow
> some rules.
>
> I think I advocate either option (2) or (3).
I'm okay with (2). I'm also okay with programmers getting (3)
by annotating the trylock/timed lock with no-acquire. My concern
is that trylock and timedlock will be common enough (particularly
if necessary to handle cancellation) that adding extra programming
rules around their simple form is going to be a persistent source
of mistakes.
--
Lawrence Crowl
More information about the cpp-threads
mailing list