I am always trying new ways to improve my pet project. Usually I put most efforts into the scheduler code.
I found a way to perform a context switch into a C function without have to use any assembler instruction.
Look at this example:
void DoSwitch(Thread *otp, Thread *ntp) {
register struct intctx *sp asm("sp");
otp->p_ctx.r13 = sp;
sp = ntp->p_ctx.r13;
asm ("" : : "r" (sp) : "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "lr");
}
The asm() tells the compiler that the function modifies all the specified registers, the compiler will save/restore all the registers into the function prologue/epilogue.
The register variable declaration enforces the compiler to allocate the variable sp into the register sp, this way it is possible to manipulate registers like normal C automatic variables.
The central instructions, save the stack pointer value into the context of the exiting thread and then loads the stack pointer of the newly executed thread.
The thing is even portable except for the register names that could be defined into a macro.
It is mostly something fun, I am not sure yet if I will use it into an official release but it is already working in a private build and it improves performance because there is one less call level in the scheduler.
LOL, I love GCC