C++ Logo


Advanced search

Re: [std-proposals] Use of volatile as function argument should not be deprecated.

From: Jason McKesson <jmckesson_at_[hidden]>
Date: Thu, 9 Jun 2022 10:15:13 -0400
On Thu, Jun 9, 2022 at 9:34 AM Ryan P. Nicholl via Std-Proposals
<std-proposals_at_[hidden]> wrote:
> There is no real reason we should need to add a new feature for what already legitimately works today.

That a thing "works" does not mean it is supposed to work this way. Or
that it makes some kind of sense. See below.

> Existing behavior of volatile was fine.

My general understanding of the reasons for the deprecation of various
uses of `volatile` was to actually *rationalize* the feature. That is,
to make it make sense and to make sure people understand that it isn't
meant to do a lot of things they thought they were doing with it.

The principal problem with `volatile` is that it got used for a lot of
things that it was never meant to do. People used it for atomics
because certain platforms guaranteed atomic access if you used basic
types that were `volatile`. That was *never* what it was meant to do
and if you've only ever programmed on platforms where that's true, you
will get a very rude awakening when you're forced to use ARM and find
all your "atomic" code stops working.

This debugging trick is *also* not what `volatile` was meant to do.
And as others have pointed out, it's not even behavior that is
required *by the standard*. Since the address of this variable is
under the complete control of the runtime, and its address is never
given out to any code that the compiler cannot see, the compiler can
be 100% certain that no external process can manipulate its value.

You might consider this all to be academic. But real programmers need
to be able to read someone else's C++ and divine what it is they're
doing from that source code. Features like `volatile` which get used
for a lot of disparate things that don't really make sense to be under
the same umbrella exacerbate this situation. Making it clear that
`volatile` is a means to interact with hardware storage that changes
outside of the C++ object model and *nothing else* would help clean up
the language.

> The new definition of volatile is considered harmful. I would hope the compiler vendors have the sense to ignore this nonsense and keep the old behavior.
> -------- Original Message --------
> On Jun 9, 2022, 00:20, Thiago Macieira via Std-Proposals < std-proposals_at_[hidden]> wrote:
> On Wednesday, 8 June 2022 20:16:50 PDT Ryan P. Nicholl via Std-Proposals
> wrote:
> > All compilers have debuggers, I don't see why we shouldn't be able to use
> > e.g. "RelWithDebInfo" and then turn on a variable. I'm pretty sure the
> > point of volatile is to eliminate the "as-if" rule for that particular
> > variable, meaning a debugger should be allowed to change the value and the
> > compiler respect that.
> That's an incorrect understanding. The language does need not take debugging
> into account. The language defines how the program runs in the abstract machine
> and volatile variables are I/O -- that is, they communicate with the outside
> world.
> Under the "as-if" rule, if the compiler can prove that no I/O is possible,
> then it *can* remove the volatile variable completely. That's what's happening
> here.
> Global variables' address can be manipulated by the linker and placed in MMIO
> regions, but if this is a possibility, then it is a contract between the
> compiler and linker. That's not possible at all for stack (automatic storage)
> variables, because there's no symbol for the linker to see in the first place.
> Therefore, stack variables simply cannot be volatile. The language in the
> standard was updated to clarify this situation, allowing the compilers to do
> what should have been there all along.
> > A register can sure be volatile if it tells the compiler not to optimize
> > away accesses or uses of that register, since the program's execution could
> > be stopped and then a debugger simply rewrite the variable.
> There's no such thing as optimisation in the standard. If you want to control
> what the optimiser of your compiler does or does not do, you need to discuss
> it with your compiler vendor.
> Volatile *general purpose* registers make no sense. Some architectures do have
> such a thing as I/O via registers, but compilers would never allocate a
> variable to them, exactly because their use would have side-effect. Conversely,
> compilers always use registers that don't have side-effects
> In a debugger, you could rewrite a variable, indeed, but that doesn't mean
> your program will proceed to run correctly. The fact that a variable has a
> current storage location somewhere your debugger can modify it does not mean
> it's the only copy or that knowledge about it wasn't used in other
> optimisations, prior to that point or after it.
> > I therefore see a perfectly legitimate way for a function parameter to be
> > volatile? It certainly isn't useful to have stack volatiles for hardware
> > programming but I have found the current implementation which allows it for
> > communication between the debugger and the program to be quite useful. I'm
> > not sure if the standard requires this behavior but I believe it does.
> I do not see it as legitimate. In your own words: "it isn't useful to have
> stack volatiles for hardware programming". That's what volatile means today
> and that's what the standard removed. Asking that it be reversed in a defect
> report implies that this determination was wrong -- and it isn't.
> I see a perfectly legitimate use-case in what you're asking, though. You may
> want to write a paper to give new meaning to the volatile keyword and address
> your use-case, but that's not the same as what you're asking right now.
> I think your best bet is to discuss this with your compiler vendor and have
> them provide a way for you to annotate somehow the sources and indicate a
> variable must be spilled to memory and that the compiler must disable
> optimisations that would assume its value stays unchanged while it is there.
> They may decide to use the volatile marker as an extension to the standard.
> > Another case is that if we did have a "volatile sig_atomic_t" as a function
> > parameter then we can pass that address to a global variable and install a
> > signal handler that uses it. There's no rule against taking the address of
> > a function argument and the calling convention is pretty irrelevant for
> > this purpose. I would suppose a volatile argument behaves the same way as
> > const, irrelevant for the caller but relevant for the definition.
> You don't need a volatile parameter for that. You can create a local variable
> for it. They cost exactly the same.
> volatile atomics (not sig_atomic_t) are practically the only valid use of
> volatile. And besides communicating with peripheral hardware via MMIO,
> asynchronous signal handlers are the only remaining situation where even
> volatile atomics make sense. They're subtly different to modifications by other
> threads of execution. This is an area of the standard that still has some
> rough edges.
> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel DPG Cloud Engineering
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

Received on 2022-06-09 14:16:41