What is saved in a context switch?
This is rather a complex question since the answer(s) are dependent on many things:
- The CPU in question
- It can vary significantly even within the same family for example the additional registers added for SSE/MMX operations.
- The operating system, since it controls the handlers which trigger on a context switch and decide whether the CPU's hardware (if any) to assist in a context switch is used or not.
- For example Windows does not use the Intel hardware that can do much of the context switch storage for you since it does not store floating point registers.
- Any optimizations enabled by a program aware of it's own requirements and capable of informing the OS of this
- Perhaps to indicate that it isn't using FP registers so don't bother with them
- In architectures with sizeable register files like most RISC designs there is considerable benefit to knowing you need only a smaller subset of these registers
At a minimum the in use general purpose registers and program counter register will need to be saved (assuming the common design of most current CISC/RISC style general purpose CPUs).
Note that attempting to do only the minimal amount of effort in relation to a context switch is a topic of some academic interest
Linux obviously has more info available on this in the public domain though my references may be a little out of date.
There is a ‘task_struct’ which contains a large number of fields relating to the task state as well as the process that the task is for.
One of these is the ‘thread_struct’
/* CPU-specific state of this task */
- struct thread_struct thread;
holds information about cache TLS descriptors, debugging registers,
fault info, floating point, virtual 86 mode or IO permissions.
Each architecture defines it's own thread_struct which identifies the registers and other values saved on a switch.
This is further complicated by the presence of rename registers which allow multiple in flight instructions (either via superscalar or pipeline related architectural designs). The restore phase of a context swicth will likely rely on the CPU's pipeline being restored in a initially empty state such the the instructions which had not yet been retired in the pipeline have no effect and thus can be ignored. This makes the design of the CPU that much harder.
The difference between a process and a thread is that the process switch (which always means a thread switch in all main stream operating systems) will need to update memory translation information, IO related information and permission related structures.
These will mainly be pointers to the more rich data structures so will not be a significant cost in relation to the thread context switch.
When the context switching is between threads of the same process, all the non-volatile general purpose registers of the current thread are saved and those of the new thread are restored; volatile registers need to be saved only if the current thread execution has been interrupted by an interrupt. Registers of any co-processor used by the threads (e.g. floating point processor), should also be saved and restored If the switching is between threads of 2 processes, in addition to what is needed for a normal context switch, memory and IO management related changes should also be done; for e.g. memory protection needed by processes is achieved using page tables and page directory tables and each process has a unique page directory table address, which has to be changed when the process changes.
This depends on the OS you're using, but for sure you'll have to save the content of all registers (including the instruction counter) and load the registers of the thread you're switching to.
The only difference that comes to my mind regarding the switch between two threads on the same process is that you don't loose the content of the L1 and MMU cache.