StuBS
Loading...
Searching...
No Matches
Context Switch

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.
 

Detailed Description

Low-Level functionality required for context switching.

Function Documentation

◆ context_launch()

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.

Parameters
nextPointer to the structure that the next context will be read from

◆ context_switch()

void context_switch ( Context * next,
Context * current )

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.

Parameters
nextPointer to the structure that the next context will be read from
currentPointer to the structure that the current context will be stored in

◆ fake_systemv_abi()

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.

◆ prepareContext()

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).

Parameters
tosPointer to the top of stack (= address of first byte beyond the memory reserved for the stack)
contextReference to the Context structure to be filled
kickoffPointer to the Thread::kickoff function
param1first parameter for Thread::kickoff function