If I understand context switching correctly, the process involves two major steps:
- The MMU is switched to one that maps the new processes virtual memory space to physical memory space.
- The processor state is saved for the current process, then switched to the saved processor state for the new process. Presumably, this includes setting the program counter to begin execution from where the switched-to process last left off.
In the kernel, the function that handles all of this is called
context_switch() (source code here). This function handles both of the required steps, but after setting the processor state, it then returns.
That's confusing, because it seems to me that once the program counter is manually moved to a new place,
context_switch() wouldn't have an opportunity to return at all. The only explanation I can come up with is that
context_switch() is both the code that switches to a new process and the code to which switched processes return. In other words, every process ends up switching from its own
context_switch() to another processes'
context_switch(). But then it seems unclear to me how this could work in a newly forked process. So maybe
context_switch() actually runs to completion and returns, and then something else jumps to the correct part of the target process?
Is this thinking correct? At what point exactly does
context_switch() move from one process to another? When does
context_switch() return? When it switches to a new process, where in the new process' execution state does it end up? How does this fit in with newly forked processes?
I've been spending the last few days reading through the relevant parts of the kernel source code to try and figure this out, but I'm afraid I'm not getting any closer to understanding. Hopefully someone here can help.