Re: goto

Linus Torvalds (Linus.Torvalds@cs.Helsinki.FI)
Sun, 23 Jul 1995 19:59:45 +0300


Tommy Thorn: "goto" (Jul 21, 16:22):
> Linus Torvalds wrote/ecrit/skrev:
> | + *
> | + * The goto is "interesting".
> | *
> ......
> | + cli();
> | + switch (current->state) {
> | + case TASK_INTERRUPTIBLE:
> | + if (current->signal & ~current->blocked)
> | + goto makerunnable;
> | + timeout = current->timeout;
> | + if (timeout && (timeout <= jiffies)) {
> | + current->timeout = 0;
> | + timeout = 0;
> | + makerunnable:
> | + current->state = TASK_RUNNING;
> | + break;
> | + }
> | + default:
> | + del_from_runqueue(current);
> | + case TASK_RUNNING:
> | + }
>
> I suppose this is the Linus Torvalds version of Fermats Last Theorem :-)
> (Leaving people wondering "why" for hundreds of years...)

Nothing strange about this at all: look at the assembly code this
generates, and you'll find that this is a good way to make gcc do better
machine code. I could have used more "goto" statements to get _exactly_
what I wanted, but this mixture of a switch and a goto gets rather good
results.

Now, looking at the code, you can obviously replace the goto statement
with the cleaner (?) "{ current->state = TASK_RUNNING; break; }". Now,
use "make kernel/sched.s" to find out what assembly code this results
in, and you'll notice that by using the goto we avoid one jump for the
common case and use some shared code instead.

(I _like_ using goto's every once in a while: it can often mess up the
gcc optimizer just enough to get better code out of it. In this case,
as the signal test is not usually true, the goto forces gcc to use
better jump placement and avoid the branch in the usual case).

As to whether it reall matters: no, it doesn't. The largest reason I do
this once in a while is that I look at the assembly gcc produces for
quite other reasons, and use a goto to make it slightly easier to read
(not the C code, the assembly ;-)

Linus