There has apparently been quite a discussion on the linux-kernel mailing list (about the use of “goto” in the kernel; kerneltrap has a good synopsis. Many people, both on the LKML and in the kerneltrap discussion, point out that “goto” can be a clean and concise way to handle complex multi-stage initialization functions that might need to “back out” at several points, and that non-goto approaches often involve extra functions, variables, or indentation so deep that the code becomes unreadable. I’m not going to argue with those points here, although there is also at least one goto-less approach to the same problems that is just as robust and performs just as well as the goto style.

No, my point is somewhat different. What I’d like to point out is that the multi-stage initialization argument is a red herring, and that goto is actually used in the Linux kernel in several far less justifiable ways. For example, “goto repeat” is used in several places instead of a simple loop, and “goto xxx” is used instead of “break” (e.g. “goto end_wait4″ in kernel/exit.c). “Goto out” – where the “out” label does nothing but return – is often used instead of an inline return. Some functions use a not-very-readable set of “goto err2″, “goto err3″ etc. The scheduler is the worst offender, with jumps to the following labels:

  • scheduling_in_interrupt
  • move_rr_last
  • still_running
  • recalculate
  • same_process
  • need_resched_back
  • repeat_schedule
  • still_running_back
  • move_rr_back

At least the label names are reasonably descriptive, but it’s a bit of a stretch to claim that the same functionality couldn’t be implemented more cleanly some other way – e.g. with an explicit mini-FSM. Some would undoubtedly claim that the scheduler is extremely performance-critical and other coding styles would cost too many cycles, but that’s just bull. The contorted control flow as it currently exists probably exacts a greater toll – mostly in terms of defeating the compiler’s attempts at register allocation and optimization – than the extra variable or two required by a more readable and less error-prone approach. I challenge anyone to provide proof – not bluster and hand-waving – to the contrary.

I’m not a goto extremist. I’ve never personally found a situation where a little thought didn’t reveal a better goto-less approach, but I’m willing to concede that such situations might exist. I’m even willing to concede that goto provides an acceptable (though not optimal) approach to the multi-stage-initialization problem. However, the Linux kernel-hacker community’s sneering response to criticism of gotos only highlights their own immaturity – not that of “brainwashed CS students” as they claim. There’s some sloppy code in the Linux kernel, and nobody benefits from denying it.