C++ Logo


Advanced search

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

From: Thiago Macieira <thiago_at_[hidden]>
Date: Wed, 08 Jun 2022 21:20:40 -0700
On Wednesday, 8 June 2022 20:16:50 PDT Ryan P. Nicholl via Std-Proposals
> 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

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

 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

Received on 2022-06-09 04:20:43