diff mbox

Clarify __atomic_compare_exchange_n docs

Message ID 20150929120038.GW12094@redhat.com
State New
Headers show

Commit Message

Jonathan Wakely Sept. 29, 2015, noon UTC
Someone on IRC incorrectly parsed the docs at
https://gcc.gnu.org/onlinedocs/gcc-5.2.0/gcc/_005f_005fatomic-Builtins.html#index-g_t_005f_005fatomic_005fcompare_005fexchange_005fn-3536
as:

  IF
  (
   desired is written into *ptr
   AND
   the execution is considered to conform to the memory model
   specified by success_memmodel.
  )
  {
   true is returned
  }
  otherwise ...

rather than the intended:

  IF ( desired is written into *ptr )
  {
   true is returned
   AND
   the execution is considered to conform to the memory model
   specified by success_memmodel.
  }
  otherwise ...

So they asked:

> What is otherwise, here? Can I make the function return false even
> when 'desired' has been written into 'ptr'? How do I do it? I could
> not write an example, so far.

This patch rewords it to avoid the ambiguity.

I've also replaced the rather clunky "the operation is considered to
conform to" phrasing. (It's only _considered_ to? So does it or doesn't
it use that memory order?) Instead I've used the terminology from the
C and C++ standards, which say "memory is affected according to".

OK for trunk?

Comments

Sandra Loosemore Sept. 29, 2015, 3:21 p.m. UTC | #1
On 09/29/2015 06:00 AM, Jonathan Wakely wrote:
> Someone on IRC incorrectly parsed the docs at
> https://gcc.gnu.org/onlinedocs/gcc-5.2.0/gcc/_005f_005fatomic-Builtins.html#index-g_t_005f_005fatomic_005fcompare_005fexchange_005fn-3536
>
> as:
>
>   IF
>   (
>    desired is written into *ptr
>    AND
>    the execution is considered to conform to the memory model
>    specified by success_memmodel.
>   )
>   {
>    true is returned
>   }
>   otherwise ...
>
> rather than the intended:
>
>   IF ( desired is written into *ptr )
>   {
>    true is returned
>    AND
>    the execution is considered to conform to the memory model
>    specified by success_memmodel.
>   }
>   otherwise ...
>
> So they asked:
>
>> What is otherwise, here? Can I make the function return false even
>> when 'desired' has been written into 'ptr'? How do I do it? I could
>> not write an example, so far.
>
> This patch rewords it to avoid the ambiguity.
>
> I've also replaced the rather clunky "the operation is considered to
> conform to" phrasing. (It's only _considered_ to? So does it or doesn't
> it use that memory order?) Instead I've used the terminology from the
> C and C++ standards, which say "memory is affected according to".
>
> OK for trunk?

This is OK, as far as it goes, but while we're at it, can we do 
something to fix the description of the weak parameter?

> @@ -9353,17 +9353,17 @@ This compares the contents of @code{*@var{ptr}} with the contents of
>  @code{*@var{expected}}. If equal, the operation is a @emph{read-modify-write}
>  operation that writes @var{desired} into @code{*@var{ptr}}.  If they are not
>  equal, the operation is a @emph{read} and the current contents of
> -@code{*@var{ptr}} is written into @code{*@var{expected}}.  @var{weak} is true
> +@code{*@var{ptr}} are written into @code{*@var{expected}}.  @var{weak} is true
>  for weak compare_exchange, and false for the strong variation.  Many targets
>  only offer the strong variation and ignore the parameter.  When in doubt, use
>  the strong variation.

What is "weak compare_exchange", and what is "the strong variation", and 
how do they differ in terms of behavior?

-Sandra
Andrew Haley Oct. 1, 2015, 11:28 a.m. UTC | #2
On 09/29/2015 04:21 PM, Sandra Loosemore wrote:
> What is "weak compare_exchange", and what is "the strong variation", and 
> how do they differ in terms of behavior?

It's in C++11 29.6.5:

Remark: The weak compare-and-exchange operations may fail spuriously,
that is, return false while leaving the contents of memory pointed to
by expected before the operation is the same that same as that of the
object and the same as that of expected after the operation. [ Note:
This spurious failure enables implementation of compare-and-exchange
on a broader class of machines, e.g., load- locked store-conditional
machines. A consequence of spurious failure is that nearly all uses of
weak compare-and-exchange will be in a loop.  When a
compare-and-exchange is in a loop, the weak version will yield better
performance on some platforms. When a weak compare-and-exchange would
require a loop and a strong one would not, the strong one is
preferable. — end note ]

The classic use of this is for shared counters: you don't care if you
miss an occasional count but you don't want the counter to go
backwards.

Whether we should replicate all of the C++11 language is perhaps
something we should discuss.

Andrew.
Sandra Loosemore Oct. 1, 2015, 5:57 p.m. UTC | #3
On 10/01/2015 05:28 AM, Andrew Haley wrote:
> On 09/29/2015 04:21 PM, Sandra Loosemore wrote:
>> What is "weak compare_exchange", and what is "the strong variation", and
>> how do they differ in terms of behavior?
>
> It's in C++11 29.6.5:
>
> Remark: The weak compare-and-exchange operations may fail spuriously,
> that is, return false while leaving the contents of memory pointed to
> by expected before the operation is the same that same as that of the
> object and the same as that of expected after the operation. [ Note:
> This spurious failure enables implementation of compare-and-exchange
> on a broader class of machines, e.g., load- locked store-conditional
> machines. A consequence of spurious failure is that nearly all uses of
> weak compare-and-exchange will be in a loop.  When a
> compare-and-exchange is in a loop, the weak version will yield better
> performance on some platforms. When a weak compare-and-exchange would
> require a loop and a strong one would not, the strong one is
> preferable. — end note ]
>
> The classic use of this is for shared counters: you don't care if you
> miss an occasional count but you don't want the counter to go
> backwards.
>
> Whether we should replicate all of the C++11 language is perhaps
> something we should discuss.

Hmmmm, yes.  Looking at the section as a whole, is it a bug in the 
implementation that the built-ins only "approximately match" the C++11 
requirements?  If there were an exact correspondence, it would only be 
necessary to point at the standard (I think it would be more helpful to 
mention <stdatomic.h> here than to cite a specific section number), 
identify what C++11 names the built-ins map onto, and to document any 
implementation-defined behavior allowed by the standard and GCC extensions.

-Sandra
Jonathan Wakely Oct. 1, 2015, 6:35 p.m. UTC | #4
On 01/10/15 11:57 -0600, Sandra Loosemore wrote:
>Hmmmm, yes.  Looking at the section as a whole, is it a bug in the 
>implementation that the built-ins only "approximately match" the C++11 
>requirements?

AFAIK they exactly match, so I don't know why the docs say that.

>If there were an exact correspondence, it would only be 
>necessary to point at the standard (I think it would be more helpful 
>to mention <stdatomic.h> here than to cite a specific section number), 

That's the C11 header, the C++11 header is <atomic>.

>identify what C++11 names the built-ins map onto,

It's pretty straightforward, I'm not sure we need to say much:

__atomic_xxx(_n)? -> atomic_xxx


>and to document any 
>implementation-defined behavior allowed by the standard and GCC 
>extensions.

There is nothing implementation-defined in the atomics clause, just
some wooly requirements like "Implementations should make atomic
stores visible to atomic loads within a reasonable amount of time."
diff mbox

Patch

commit 370a92b7f4d318957a70d0d3f1185f1c6f282ff3
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Tue Sep 29 12:45:21 2015 +0100

    	* doc/extend.texi (__atomic Builtins): Clarify compare_exchange
    	effects.

diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 8406945..0de94f2 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -9353,17 +9353,17 @@  This compares the contents of @code{*@var{ptr}} with the contents of
 @code{*@var{expected}}. If equal, the operation is a @emph{read-modify-write}
 operation that writes @var{desired} into @code{*@var{ptr}}.  If they are not
 equal, the operation is a @emph{read} and the current contents of
-@code{*@var{ptr}} is written into @code{*@var{expected}}.  @var{weak} is true
+@code{*@var{ptr}} are written into @code{*@var{expected}}.  @var{weak} is true
 for weak compare_exchange, and false for the strong variation.  Many targets 
 only offer the strong variation and ignore the parameter.  When in doubt, use
 the strong variation.
 
-True is returned if @var{desired} is written into
-@code{*@var{ptr}} and the operation is considered to conform to the
+If @var{desired} is written into @code{*@var{ptr}} then true is returned
+and memory is affected according to the
 memory order specified by @var{success_memorder}.  There are no
 restrictions on what memory order can be used here.
 
-False is returned otherwise, and the operation is considered to conform
+Otherwise, false is returned and memory is affected according
 to @var{failure_memorder}. This memory order cannot be
 @code{__ATOMIC_RELEASE} nor @code{__ATOMIC_ACQ_REL}.  It also cannot be a
 stronger order than that specified by @var{success_memorder}.