6

What is the best way to implement the busy loop ? correct me if i am wrong ?

while (1); // obviously eats CPU. 
while (1) { sleep(100); } // Not sure if it is the correct way ?
Michael Berkowski
  • 267,341
  • 46
  • 444
  • 390
Whoami
  • 13,930
  • 19
  • 84
  • 140
  • 11
    What are you trying to do? – Mat Oct 01 '11 at 12:38
  • 2
    If you're trying to simulate a heavy thread, it's right. – Thinhbk Oct 01 '11 at 12:41
  • you can sleep(1) if you only want to yield to OS instead of throttling. – artificialidiot Oct 01 '11 at 12:48
  • Mat, my tiny application associates SIGUSR1, and some other signals with user define signal handler. and i want the main program not to die. – Whoami Oct 01 '11 at 12:50
  • 1
    @user916439: If you want your app to do nothing, _busy looping_ is what you want to **avoid**. That term is used to describe code the uses CPU continually while waiting for something to happen. Your second piece of code is much better if you just want to do nothing without consuming CPU. – Mat Oct 01 '11 at 12:53
  • `sleep()` is NOT what is called a 'busy loop'. You can't busy sleeping. – J-16 SDiZ Oct 01 '11 at 13:28

4 Answers4

8

To do an infinite wait, for a signal (what else) there is the pause() system call. You'll have to put it in a loop, as it returns (always with -1 and errno set to EINTR) every time a signal is delivered:

while (1)
    pause();

As a curious note, this is, AFAIK the only POSIX function documented to always fail.

UPDATE: Thanks to dmckee, in the comments below, sigsuspend() also fails always. It does just the same as pause(), but it is more signal-friendly. The difference is that it has parameters, so it can fail with EFAULT in addition to EINTR.

rodrigo
  • 94,151
  • 12
  • 143
  • 190
  • It is in `unistd.h`. Please see `man 2 pause` or `man 3 pause` for details, or see it [online](http://pubs.opengroup.org/onlinepubs/000095399/functions/pause.html). – rodrigo Oct 01 '11 at 13:15
  • Nice. However, the man page on my Mac OS 10.5 box says *" Pause is made obsolete by sigsuspend(2)."* (which also seem to exhibit the always fail behavior and conforms to POSIX.1). Take that for what you will. – dmckee --- ex-moderator kitten Oct 01 '11 at 13:46
  • @dmckee Well, obsolete is such an awful word, it is still not deprecated, though. But yes, `sigsuspends()` always fails too, so I'm updating my trivial database... – rodrigo Oct 01 '11 at 13:53
  • It could be worse...`getpass` [was "LEGACY" in SUSv2 and has actually been *removed* from POSIX](http://linux.die.net/man/3/getpass) but *doesn't* have a universal replacement! – dmckee --- ex-moderator kitten Oct 01 '11 at 13:57
3

Busy loop is loop that never blocks and continuously checks some condition. Small sleep is good enough to avoid 100% cpu usage.
The best way to implement busy wait is to not implement it. Instead of it you can use blocking calls or callbacks.

Matvey Aksenov
  • 3,802
  • 3
  • 23
  • 45
2

Linux has had the (POSIX 1.g) pselect for some time now. If you are using signal handlers or user-defined signals, I think this is worth investigating. It also addresses some subtle race conditions that manifest in other approaches.

I know you mentioned the 'busy loop', but I think a 'blocking loop' is what you're after.

Brett Hale
  • 21,653
  • 2
  • 61
  • 90
0

How to prevent it from being optimized away with data dependencies

First of course, you should only use busy loops if you have very good reason to not use non-busy ones, which are generally more efficient, see: https://codereview.stackexchange.com/questions/42506/using-a-for-loop-or-sleeping-to-wait-for-short-intervals-of-time

Now, focusing only on busy loops, if you just write something like:

while (1);

or:

for (unsigned i = 0; i < 100; i++);

then both of those can be optimized away as mentioned at: Are compilers allowed to eliminate infinite loops?

For this reason, as explained in detail at: How to prevent GCC from optimizing out a busy wait loop? I would write them as:

while (1) asm("");

or:

for (unsigned i = 0; i < 100; i++) {
    __asm__ __volatile__ ("" : "+g" (i) : :);
}
Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
  • 1
    Thanks! FWIW I found this useful to read more on `__asm__` syntax used here: https://www.felixcloutier.com/documents/gcc-asm.html – Eric Cousineau May 27 '21 at 03:24