|
StuBS
|
Low-Level functionality required for context switching. More...
Classes | |
| struct | Context |
| Structure for saving the CPU context when switching coroutines. More... | |
Functions | |
| void | prepareContext (void *tos, Context &context, void(*kickoff)(void *), void *param1=nullptr) |
| Prepares a context for its first activation. | |
| void | context_switch (Context *next, Context *current) |
| Executes the context switch. | |
| void | context_launch (Context *next) |
| Launch context switching. | |
| void | fake_systemv_abi () |
| Fakes a SystemV abi call. | |
Low-Level functionality required for context switching.
| void context_launch | ( | Context * | next | ) |
Launch context switching.
To start context switching, the current context (from the boot-routines) is thrown away and the prepared register values within the given next context replace it.
This function must be implemented in assembler in the file context.asm (why?). It must be declared as extern "C", so assembler functions are not C++ name mangled.
| next | Pointer to the structure that the next context will be read from |
Executes the context switch.
For a clean context switch, the current register values must be stored in the given context struct. Subsequently, these values must be restored accordingly from the next context struct.
This function must be implemented in assembler in the file context.asm (why?). It must be declared as extern "C", so assembler functions are not C++ name mangled.
| next | Pointer to the structure that the next context will be read from |
| current | Pointer to the structure that the current context will be stored in |
| void fake_systemv_abi | ( | ) |
Fakes a SystemV abi call.
When a thread is first started, only non-volatile registers are "restored" from our prepared context (which is where we stored our Thread::kickoff parameters). However, the 64 bit calling convention (SystemV) dictates that parameters are passed via the volatile registers rdi, rsi, rcx, rdx, r8, r9. In order to call a C++ function, we have to transfer our parameters from the non-volatile registers (e.g. r15, ...) to the correct volatile ones (rdi, ...).
This function must be implemented in assembler in the file context.asm (why?). It must be declared as extern "C", so assembler functions are not C++ name mangled.
| void prepareContext | ( | void * | tos, |
| Context & | context, | ||
| void(* | kickoff )(void *), | ||
| void * | param1 = nullptr ) |
Prepares a context for its first activation.
On first activation (during some context switch), the execution of a thread should start at its entry point (typically an implementation of Thread::kickoff).
For this, we have to prepare the thread context such that context_switch and context_launch can work with it.
Just pushing the entry point onto the stack as a return address is not sufficient, however. Thread::kickoff requires a pointer to the current thread as a parameter, which we also have to transfer. According to the 64 bit SystemV calling convention, parameters are passed via the volatile registers rdi, rsi, rcx, rdx, r8, r9. But theses are never set during the initial context switch (why?). Therefore we pass the parameter using the non-volatile register r15 and use a trampoline function as the actual entry point. See fake_systemv_abi for details.
prepareContext() can be implemented in the high-level programming language C++ (in file context.cc).
| tos | Pointer to the top of stack (= address of first byte beyond the memory reserved for the stack) |
| context | Reference to the Context structure to be filled |
| kickoff | Pointer to the Thread::kickoff function |
| param1 | first parameter for Thread::kickoff function |