Groups | Search | Server Info | Login | Register


Groups > comp.std.c > #6665

Re: 7.17.7.5 The atomic_fetch and modify generic functions and "address types"

From Keith Thompson <Keith.S.Thompson+u@gmail.com>
Newsgroups comp.std.c
Subject Re: 7.17.7.5 The atomic_fetch and modify generic functions and "address types"
Date 2025-01-01 21:32 -0800
Organization None to speak of
Message-ID <87a5c9u6fc.fsf@nosuchdomain.example.com> (permalink)
References <vkn8da$3rj4n$1@dont-email.me> <86r05lalbd.fsf@linuxsc.com>

Show all headers | View raw


Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
> Andrey Tarasevich <andreytarasevich@hotmail.com> writes:
>> 7.17.7.5 says (https://port70.net/~nsz/c/c11/n1570.html#7.17.7.5)
>>
>>> 1 The following operations perform arithmetic and bitwise
>>> computations.  All of these operations are applicable to an object of
>>> any atomic integer type.  None of these operations is applicable to
>>> atomic_bool.
>>
>> If I understand it correctly, this wording is intended to restrict
>> these operations to integers types only.  I.e. they shall not be
>> applied to atomic pointer types.  Is that correct?
>
> I believe the intent is that the atomic_fetch_key() family of
> functions may be called with either atomic integer types or atomic
> pointer types (with the possible exception of atomic boolean types).
>
> If the committee had meant to rule out atomic pointer types, the
> standard could have given an explicit statement to that effect, like
> what was done for atomic boolean types.  The standard does not
> include any explicit statement ruling out the use of atomic pointer
> types;  if anything atomic pointer types are implicitly included by
> the parameter type name A, which is described in 7.17.1 paragraph 5
> (paragraph 6 in some later versions of the standard).
>
> Similarly, if the committee had meant to rule out atomic pointer
> types, there is no reason for the last sentence in paragraph 3,
> talking about what behaviors are allowed when address types are
> used.  Presumably the phrase "address types" is meant to be the same
> as "pointer types" (see also below), which seems like the only
> plausible interpretation.

I think the only plausible explanation is that "address types" refers to
atomic_address, a type that was specified in N1547 but dropped some time
before N1570 (though I'm not sure why it's plural.)

> There is no reason to think the inclusion of the last sentence of
> paragraph 3 is an oversight.  This sentence has survived unchanged
> for more than 14 years, going back to at least 2010.  But other
> parts of section 7.17 were changed significantly during that time;
> hence it seems unlikely that such an important incongruity was
> missed over all of that time.
>
> Why then does the standard take the trouble to say that these
> operations are applicable to atomic integer types?  I think the
> confusion comes from reading "applicable" as "allowed".  A more
> consistent reading is for "applicable" to mean "well-defined".

I think that's a bit of a stretch.  If that's the intent, it should just
say "well-defined" (or just "defined").  The standard should say what it
means by "applicable", or it should be worded more clearly.

Given the current wording, I suppose applying atomic_fetch_add() to
atomic_bool would have undefined behavior.  IMHO making it a constraint
violation would have made more sense (but constraints appear only in
section 6 of the standard).

>                                                                 All
> of the atomic_fetch_key() family of functions are well-defined for
> all inputs of atomic integer type, even going so far as to stipulate
> two's complement with wraparound for signed types (and this at a
> time when the C standard did not require two's complement for signed
> integer types generally).  Atomic pointer types do not have this
> property of producing well-defined results.  Indeed, there is a
> limited degree of undefined behavior that may result.  In that sense
> the operations of atomic_fetch_key() are not fully applicable to
> atomic pointer types.  But not applicable does not mean disallowed.

>> Later 7.17.7.5 also says
>>
>>> 3 For address types, the result may be an undefined address, but the
>>> operations otherwise have no undefined behavior.
>>
>> However, I was unable to find any mention of "address types" anywhere
>> in the standard.  What types are "address types"?
>
> The phrase "address types" is a holdover from earlier drafts of the
> C standard.  It's instructive to compare N1547, a draft from
> December 2010, to N1570, a draft from April 2011.  The phrase
> "address types" is used in several places, including to describe a
> type name "atomic_address" (a struct type).  I won't go through all
> of the differences, which are fairly widespread.  But looking them
> over is I think convincing that pointer types were left in
> deliberately.

N1574 specifies a type "atomic_address", which didn't survive into C11
(good catch, BTW).  N1574 7.17.7.5 says that the atomic_fetch_*
functions (only addition and subtraction, a distinction that doesn't
appear in N1570) are applicable to atomic_address, not to atomic pointer
types in general.  I see no indication that the functions are meant to
be "applicable" to atomic pointer types.

The phrase "address types" should have been changed to "pointer types",
*if* that's what was intended.

Certainly atomic pointer types are valid.  The question is which of the
atomic_fetch_* and atomic_modify_* function can be (meaningfully)
applied to them.

If the _add and _sub functions are applied to an atomic pointer type, is
the unit of addition or subtraction one byte or one element?  N1547
explicitly says that it's one byte for atomic_address.  Addition and
subtraction by elements is the only thing that makes sense for atomic
pointer types, but the standard doesn't specify it.

> A point that needs clarifying is whether bitwise operations are
> allowed for atomic pointer type.  The bitwise operations are allowed
> by gcc, and disallowed by clang.  I think an argument can be made
> either way.  Personally I think allowing bitwise operations is more
> compelling than disallowing them, but I have to acknowledge the
> possibility that the intent was place them off limits (meaning,
> requiring a diagnostic).  That said, I don't see any explicit text
> in the standard that forces that conclusion.

There's nothing in the standard to suggest that _add and _sub should be
valid for atomic pointer types but _or, _xor, and _and should not.  But
IMHO there should be.  Addition and subtraction of (atomic) pointer
types could be well defined; bitwise operations are not.

The simplest explanation is that this is a flaw in the standard.
It happens.

[...]

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
void Void(void) { Void(); } /* The recursive call of the void */

Back to comp.std.c | PreviousPrevious in thread | Find similar


Thread

7.17.7.5 The atomic_fetch and modify generic functions and "address types" Andrey Tarasevich <andreytarasevich@hotmail.com> - 2024-12-27 14:06 -0800
  Re: 7.17.7.5 The atomic_fetch and modify generic functions and "address types" Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2024-12-27 17:24 -0800
  Re: 7.17.7.5 The atomic_fetch and modify generic functions and "address types" Tim Rentsch <tr.17687@z991.linuxsc.com> - 2025-01-01 20:31 -0800
    Re: 7.17.7.5 The atomic_fetch and modify generic functions and "address types" Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-01-01 21:32 -0800

csiph-web