C++ Logo

sg14

Advanced search

Re: [SG14] Challenging the deprecation of volatile compound statements

From: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Date: Fri, 12 Feb 2021 11:36:35 -0500
On Fri, Feb 12, 2021 at 10:38 AM connor horman via SG14 <
sg14_at_[hidden]> wrote:

> On Fri, Feb 12, 2021 at 10:29 connor horman <chorman64_at_[hidden]> wrote:
>
>> If I may add my $.02, I would like to add my experience in targetting
>> (albeit not completely) the 65816 processor, and in particular, the Super
>> Nintendo Entertainment System. In my case (since I provide symbols to users
>> (and those users are primarily myself), rather than macros) refactoring to
>> a = a_at_v would not be an issue, though it is a bit unwieldy over a@=v
>> (not so much to cause anything more than minor annoyance).
>>
>
Examples would be useful.
Again, the null hypothesis is that people don't do this; we'll have to show
some concrete examples from real codebases in order to provide evidence
against the null hypothesis.

[...]

> Your use of the passive voice in the last sentence hurts you. "Would only
>>> be replaced" by whom?— the compiler, or the human programmer? If the human
>>> programmer is supposed to replace `x &= y` with `x = x & y` in order to
>>> avoid ISR/multithreading bugs, then *good*, that's exactly what C++20
>>> wants them to do. IOW, I don't understand the thrust of this paragraph.
>>>
>> I would argue that, as the standard is written, both would be equally
>> susceptible to bugs caused by accessing things which are also modified in
>> ISRs (My solution was to save the value of the hardware registers and a
>> number of MMIO registers into a special region of memory as part of the
>> prelude of interrupt handlers). To me, it seems easier to allow x &= y to
>> be in-place, for implementations where this matters, than x = x & y;,
>> which, as written, seems like it would always have to imply a separate read
>> and write to x.
>>
>
"To me, it seems easier to allow x &= y to be in-place, for implementations
where this matters" — Well, that's the thing. If it matters to the
programmer, then it should be expressed explicitly in the code — perhaps
via inline assembly. Otherwise, you end up in this awkward situation:
    x &= y; // Maintainers take note! It matters for business reasons that
this is in-place on x86, *but* on ARM and PPC it is load-modify-store (and
that's OK)
How can atomicity "matter" on some platforms, and yet be unimplementable on
others?
That level of platform-specificity should be expressed via inline assembly,
or at least hidden behind an (inline) helper function.


Oh, and finally, consider the following workaround:
>>>
>>> *(int*)myvolatilevar &= 255;
>>>
>>> Compound assignments on non-volatile variables aren't deprecated; so if
>>> you really need the compound stuff more than any particular semantics
>>> provided by the volatile stuff, could you just add the cast?
>>>
>> Isn't accessing a volatile object through a non-volatile lvalue undefined
> behaviour?
>

Yes, but in real life I would guess that we don't have a volatile object
here; we just have something like
    volatile int& myvolatilevar = *(volatile int*)0xDEADBEEF;
Maybe we do have a volatile global variable and use linker directives to
put it at the right location? I don't know. Again, the null hypothesis is
that this never happens, and we'd have to see some concrete examples from
real codebases in order to provide evidence against the null hypothesis.

–Arthur

Received on 2021-02-12 10:36:48