On 24 October 2011 20:05, Michael K. Edwards m.k.edwards@gmail.com wrote:
The calling convention for makecontext() isn't just an issue for standards lawyers, it's an actual problem on ARM, especially on hard-float systems. According to the standard, "The application shall ensure that the value of argc matches the number of arguments of type int passed to func; otherwise, the behavior is undefined." If you read this to imply that func() must be a non-variadic function that takes zero or more int arguments, and call it as if it took exactly as many int arguments as fit in registers -- stuffing extras onto the stack if necessary -- then you're OK. But supporting more general calling conventions for func() gets hairy, and correctly supporting both variadic and non-variadic functions on a hard-float system is impossible.
FWIW, the function QEMU uses is: static void coroutine_trampoline(int i0, int i1), so we are not trying to take advantage of the hairier cases.
Note that you will need to save/restore FP state in all swapcontext() calls. User thread context switch code doesn't have access to the FPEXC register and thus can't identify non-FP-using contexts and skip the q4-q7 save/restore. However, the standard is silent on whether you can have context-specific settings of floating point exception control, rounding mode, etc. If QEMU's coroutines need this, you'll need to save/restore FPSCR as well.
As it happens QEMU coroutines use swapcontext() only as a way to initially switch to a newly allocated stack -- actual switching between coroutines is done via setjmp()/longjmp(). (On reflection this does seem a bit odd...)
(the actual code is here: http://git.linaro.org/gitweb?p=people/pmaydell/qemu-arm.git%3Ba=blob%3Bf=cor... )
-- PMM