
The printk() function is a subject of much ongoing consternation among kernel developers. Ostensibly, it's just an output routine for sending text to the console. But unlike a regular print routine, printk() has to be able to work even under extreme conditions, like when something horrible is going on and the system needs to utter a few last clues as it breathes its final breath.
It's a heroic function. And like most heroes, it has a lot of inner problems that need to be worked out over the course of many adventures. One of the entities sent down to battle those inner demons has been John Ogness, who posted a bunch of patches.
One of the problems with printk() is that it uses a global lock to protect its buffer. But this means any parts of the kernel that can't tolerate locks can't use printk(). Nonmasking interrupts and recursive contexts are two areas that have to defer printk() usage until execution context returns to normal space. If the kernel dies before that happens, it simply won't be able to say anything about what went wrong.
There were other problems—lots! Because of deferred execution, sometimes the buffer could grow really big and take a long time to empty out, making execution time hard to predict for any code that disliked uncertainty. Also, the timestamps could be wildly inaccurate for the same reason, making debugging efforts more annoying.
John wanted to address all this by re-implementing printk() to no longer require a lock. With analysis help from people like Peter Zijlstra, John had come up with an implementation that even could work deep in NMI context and anywhere else that couldn't tolerate waiting.
Additionally, instead of having timestamps arrive at the end of the process, John's code captured them at execution time, for a much more accurate debugging process.
His code also introduced a new idea—the possibility of an emergency situation, so that a given printk() invocation could bypass the entire buffer and write its message to the console immediately. Thus, hopefully, even the shortest of final breaths could be used to reveal the villain's identity.
Sergey Senozhatsky had an existential question: if the new printk() was going to be preemptible in order to tolerate execution in any context, then what would stop a crash from interrupting printk() in order to die?
John offered a technical explanation, which seemed to indicate that "panic() can write immediately to the guaranteed NMI-safe write_atomic console without having to first do anything with other CPUs (IPIs, NMIs, waiting, whatever) and without ignoring locks."