Each core in each processor runs exactly one task at all times. If some user-mode code is running and an interrupt occurs, the processor stops, switches to kernel-mode, pushes the instruction pointer onto the stack and then starts executing the handler for that interrupt.
The handler first saves all the registers (including the stack pointer), loads the kernel-mode stack, and then does whatever needs to be done (ie. if it's a notification that a key was pressed it might add the key to a queue of keypresses to be processed). Next, the scheduler runs (even if it's not a timer interrupt, the OS will practically always take the opportunity to switch tasks anyway because it's very little extra cost).
The scheduler finds the next thread to run (usually the one that hasn't run for the longest) and tells the dispatcher to switch to that thread. Switching to a thread involves restoring all the registers (including the stack pointer) for that thread and then performing an "IRET" (interrupt return) which is the only way to switch to user-mode.
Since the restored stack has the instruction pointer on top for where that thread was interrupted, it will automatically be popped off by the processor and execution will continue from that point.
There is a slight difficulty though: although the above mechanism makes it very easy to resume a thread that was previously interrupted, there's apparantly no way to create a new thread (since the only way to enter user-mode is with an IRET. The way to do this is to pretend that it was previously interrupted: manufacture a new stack with the desired instruction pointer on top, set the stack pointer to this new stack and perform an IRET.
So, in short, the dispatcher is just a very few bytes of code in the kernel which restore the registers of a given thread
[b]
