Often, your kernel or driver code will need to wait for a given time before moving on to the next instruction. This can be achieved within the Linux kernel space via a set of delay APIs. Right from the outset, a key point to understand is that you can enforce a delay in two broad ways:
- Delay via non-blocking or atomic APIs that will never cause a sleep process to occur (in other words, it will never schedule out)
- Delay via blocking APIs that cause the current process context to sleep (in other words, by scheduling out)
(As we covered in detail in the companion guide Linux Kernel Programming, our chapters on CPU scheduling  Chapter 10, The CPU Scheduler – Part 1, and Chapter 11, The CPU Scheduler – Part 2), putting a process context to sleep internally implies that the kernel's core schedule() function is invoked at some point, ultimately causing a context switch to occur. This leads up...