deckard026354 wrote on Wednesday, July 04, 2012:
Greetings.
Looking at the logic for yield_FROM_WITHIN_API and the ARM7 code that goes with it in two places
xTaskResumeAll();
There is a case where we call portYIELD_WITHIN_API() line 1236.
On the SAM7 port this will call the naked function vPortYieldProcessor() which will setup the next return instruction to do a context-swtich
void vPortYieldProcessor( void )
{
/* Within an IRQ ISR the link register has an offset from the true return
address, but an SWI ISR does not. Add the offset manually so the same
ISR return code can be used in both cases. */
asm volatile ( “ADD LR, LR, #4” );
/* Perform the context switch. First save the context of the current task. */
portSAVE_CONTEXT();
/* Find the highest priority task that is ready to run. */
vTaskSwitchContext();
/* Restore the context of the new task. */
portRESTORE_CONTEXT();
}
We call into taskEXIT_CRITICAL() - portEXIT_CRITICAL() - which shouldn’t corrupt any of the contents of the registers populated by portRESTORE_CONTEXT();
However the return xAlreadyYielded will overwrite a register ?
On x86 return xAlreadyYielded would result in %eax being overwritten - on the specific example called out for ARM7 I believe that chunk of code “return xAlreadyYielded” after the call to the naked function will result in %r0 from the portRESTORE_CONTEXT() being overwritten.
This will be the case for any CPU architecture that defines particular registers to hold procedure return values.
In simple terms the problem is this can happen:
int yield_test(void)
{
portYIELD_WITHIN_API();
return 0x12345678;
}