C++ Logo


Advanced search

Re: Remove infinite loop UB

From: connor horman <chorman64_at_[hidden]>
Date: Sat, 9 May 2020 08:14:38 -0400
On Sat, May 9, 2020 at 05:05 Andrey Semashev via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> On 2020-05-09 04:02, connor horman via Std-Proposals wrote:
> > Currently in the C++ language, it is undefined behaviour to have an
> > infinite loop without observable side effects. While this is nice on
> > paper, it has a few issues. Any time you need to loop forever, you
> > basically need to insert a (potentially costly) side effect. This
> > applies any time you need are, say, running a game on a old console, and
> > just need to spin while waiting for interrupts to do stuff (same with an
> > os kernel). This results in requiring assembly to so this, or maybe
> > insert an instruction to wait for an interrupt in a loop (both llvm and
> > gcc allow the volatile specifier in an assembly declaration, which is
> > treated as observable, so x86_64 code could use hlt (in CPL=0), 65816
> > could WAI). This, however, seems to violate one of C++'s core
> > principles, that there is no lower level language.
> > A further case would be an init process on linux, which cannot terminate
> > (doing so results in a kernel panic), nor can just call hlt in a loop,
> > as that's one way to get a #GP which probably translates to SIGILL. Once
> > an init process is done setting up, it could want to just spin forever,
> > and do so using as little system resources as possible. The logical idea
> > would be just for(;;) std::this_thread::yield();, but that would be UB
> > as yield() is not observable (correct me if I'm wrong).
> yield() is potentially observable because it may result in execution of
> a thread that has observable behavior.
> > Having the ability to spin forever, without wasting time actually doing
> > stuff, seems like a reasonable thing to have in low-level code, so its
> > very curious (and in many cases, annoying) that you cannot actually do
> > this in real code that might have to.
> I don't believe you really are spinning forever, as that would be a
> rather useless program. Every time you say you're spinning *waiting for
> something*, you already have a termination condition - it's when that
> something happens. You may have phrased that weirdly in the code, which
> makes it look like an infinite loop, but you should be able to do it the
> right way.

For a SNES Game (on a 65816). The actual thing I'm "waiting" for in some
cases is a power down or a RESET. Both of which cannot be detected
programatically, nor triggered programatically. For the most part I'm
waiting for an interrupt to do stuff in that interrupt. When I receive a
VBLANK NMI, I have to do all the dma transfers to within the interrupt
handler (in case I overrun the VBLANK time frame, the FBLANK is still set
until I use RTI). Once I return from that interrupt, there is nothing more
for the main "thread" to do, except wait for the next one or RESET.

> For example, if you're waiting for an interrupt, then in terms of your
> program you must be waiting until a std::sig_atomic_t variable becomes
> true, and set that variable to true in the signal handler.

I'm not waiting for an interrupt to continue, I'm waiting for an interrupt
because there is nothing else to do but handle VBLANKs and wait for a
shutdown or RESET. Literally anything else that needs to be done is (and
can only be) done within the interrupt handler, so the thing the main
thread has to do is simply spin. "Waiting" for interrupts in this case
simple means I'm doing something slightly smarter in this case to reduce
power (by disabling the system clock until an interrupt is recieved).

This is also somewhat common at the end of an embedded program. Spin
forever until the processor resets or is shut down.

> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

Received on 2020-05-09 07:17:51