4

I've always read/heard that context switching is expensive. I recently started reading Robert Love's "Linux Kernel Development" and have made it through the Processes and Process Scheduling chapter. This gave me some insight into the cost of context switching between different processes and threads (as threads are treated as processes). I wanted to scratch this itch to really understand the cost of context switching, ideally in rough terms of number of instructions and time lost.

For simplicity's sake, let's assume a single core processor that's running two processes with equal niceness weighting (proc1 and proc2). Also, let's assume targeted latency is 20ms, therefore, each process is scheduled for 10ms. When a context_switch occurs, I'm assuming that while context_switch happens, proc1 is suspended. At this point, proc2 is suspended as well? So does this mean that the active process is some kernel thread or process? And if that's the case, does this mean both proc1 and proc2 are unable to get 10ms of runtime within the targeted_latency? E.g. (numbers are just for demonstration):

+-----------20ms-----------+

|---proc1---|--|---proc2---|
^____9ms____^__^____9ms____^
             |
            2ms of kernel executing context_switch()

And if this is what happens, does context_switch() from one process to another ultimately call context_switch() twice? Once to go from proc1 to kernel thread, then another to go from kernel thread to proc2?

3
  • 1
    it helps if you momentatrily take a step back from your concept of "process" and ask yourself "what is the CPU doing?"; you'll find that you can quite clearly pinpoint what happens (a timer goes off, an interrupt fires, the interrupt handling happens in kernel memory space, and then the kernel chooses which memory tables to load and what to jump to) Dec 12, 2021 at 2:04
  • 1
    with other words, don't think of software doing something, being the actor – just think of the CPU fetching and executing instructions, which do things to the state. The software is being executed, it's not "executing" itself. Then you'll see that hey, the CPU at some point gets an address from proc1's code loaded into its program counter register, and executes what is there, until something interrupts that – either a syscall "software interrupt", or some hardware interrupt, a timer, a netwokr card, a storage device, USB... Dec 12, 2021 at 2:06
  • 1
    The concept of "active thread" makes no sense at that point. Dec 12, 2021 at 2:09

1 Answer 1

8

There are as many answers to this as there are operating system versions. No single answer covers everything.

Basically, the cost of context switching is the cost of saving all of the cpu state relating to the process context, and then loading in the context of a new process.

What exactly is saved is highly dependent on not just the operating system but the cpu hardware itself. For example, processors like the Intel cpus have lots of registers that have to be saved somewhere and then reloaded with the other process's context, while the sparc cpu keeps most of its context including all cpu registers on the stack, so a context switch is a matter if just moving the stack pointer to a different register window.

On the other hand, most modern cpus have some of their state in cpu cache memory, and while this is not typically swapped during a context switch, use of memory can cause cache lines to be unloaded and reloaded as the new process executes, so that when switching back to the previous process, its cache lines may need to be reloaded. While this isn't a direct cost of context switching, it still is there.

There are many other resources in the cpu that need to be switched, such as page maps, permission bits, etc., and the list is different on each cpu model and handled differently by each operating system.

You reference processes vs. threads. At one time, there were vast differences between them, and threads had much less context that needed switching. Then threads as light weight processes were created, so now there is very little difference, and processes are nearly as light as threads were.

Also, modern cpus are designed for multitasking operating systems and include features that try to lighten the cost of context switches. But even when context switches were more expensive, there were many mitigations for this. For instance, some unixes had real time features in their schedule that differentiated between an interactive process, which needs to do computing in short bursts and then wait for user interaction, vs. pure computation threads with minimal I/O interaction. In these two cases, the scheduler can give the interactive thread very short scheduling intervals that get high priority, while giving the computational process longer intervals with lower priority and fewer context switches to lower the overhead.

So modern operating systems mostly don't use fixed length scheduling intervals, because this can't adapt to workloads. And there is a mix of cooperative multitasking (where a process can relinquish its time slice early) and time based forced context switches.

Some cpus even support scheduling at different rates on different cores, so you could have an interactive core with short time slices and a computation driven core with longer time slices.

This is the tip of the complexity of this topic, with more than 50 years of research and development to optimize it for many different work loads and hardware capabilities. Entire books have been written on this topic, a short answer here can only gloss through the details.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .