"Nested" context switch

Hi, I just wanted to ask if it should be possible to execute a context switch at the end of the interrupt handler after interrupting the core while it was executing another context switch. For example this could happen in the Cortex-A9 port if the FreeRTOS_SWI_Handler is interrupted by the SysTick interrupt and xTaskIncrementTick requires a context switch.

I would expect that the code would have any code needing protection for that to be inside a critical section, thus disabling interrupts.

The reason why I am asking is that some ports, like the RP2040 in both single-core and multi-core, disable the interrupts before entering vTaskSwitchContext whilst the Cortex-A9 port doesn’t.

For ports like RP2040 , the process for saving the context and restoring the context is done in C, inside the PendSV handler . As a result, vTaskSwitchContext() could be interrupted, potentially leading to inconsistent state if, SysTick fires mid-way. So they disable interrupts to guard it.

For ports like Cortex-A9 port, the SVC handler (triggered by portYIELD()) runs in SVC mode, which is an exception mode.
From ARM documentation

Exceptions are handled in a fixed priority order, and an exception of a given priority cannot preempt another exception of the same or higher priority. Specifically, while an exception handler is executing, the processor masks exceptions of the same or lower priority to prevent reentrancy.

Therefore, when the processor is handling an SVC exception, it will not accept another SVC exception until the current handler has completed. This hardware-enforced behavior ensures that SVC handlers are not reentrant. As a result for these ports, the call to vTaskSwitchContext() happens within an atomic section enforced by the hardware - SVC mode itself is the guard.

Thanks for the detailed reply. While I agree with you that if the processor enters SVC mode to handle such exception there is no way another exception of the same type can be handled, that was not what my initial problem. My program was servicing the SysTick interrupt within FreeRTOS_SWI_Handler and I couldn’t understand why. After looking through some of the ARMv7-A documentation I discovered that when an exception is taken the I bit of the CPSR is automatically set. Apparently, I was mistakenly enabling interrupts by calling ulPortSetInterruptMask and vPortClearInterruptMask inside taskCHECK_FOR_STACK_OVERFLOW.

Thank you for sharing! You are right that the core disables interrupts upon taking an exception. The corresponding handler may decide to enable them explicitly but SWI handler never enables them.