Question about taskYIELD()

In xQueueSend() (and xTaskResumeAll() and some others) there is a call to taskYIELD() inside a taskENTER_CRITICAL()/taskEXIT_CRITICAL() section. In our implementation interrupts are disabled inside the critical section, so our tick interrupt won’t run. We’re running preemptive as well. Is there any possible problems with getting tasks to switch, or losing ticks? Dan Searles

Question about taskYIELD()

It is the intended behaviour that the context switch occurs within the critical section – this allows the use of the scheduler locking mechanism.  Each task should maintain its own interrupt status.  Therefore a task that has interrupts disabled can call taskYIELD(), and switch to a task that may have interrupts enabled.  When the original task next runs it starts with the interrupts in the state in which it expects to find them – disabled.  Therefore this mechanism does not mean that interrupts remain disabled until the task executes again. Regards.

Question about taskYIELD()

Hi there, I’m trying to port FreeRTOS now to CEVA DSP and I have a question which seems to me to be a compliment to the above discussion: In my understanding taskYield() should always be called from the critical section  since it actually performs context switch. However in the code of the task.c there are places where taskYield() is called outside the portENTER_CRITICAL/portEXIT_CRITICAL macros. E.g. in the vTaskSuspend method, xTaskresumeAll and some other places. Was this done intentionally ? If yes, what is the reason? Thank you, Igor.

Question about taskYIELD()

taskYIELD() absolutely MUST be implemented so that it can be called either from within a critical section OR from outside of a critical section.  If called from within a critical section then when the task that made the taskYIELD() call next runs it must re-start also from within the same critical section (with interrupts disabled). If called from outside a critical section, then when the task that made the taskYIELD() call next runs it must re-start also from outside a critical section (with interrupt enabled). Regards.

Question about taskYIELD()

Since taskYIELD can be called from outside critical section, and since taskYIELD typically calls vTaskSwitchContext, then vTaskSwitchContext may end up being called from outside critical section. This appears to be the case in the GCC ATMega323 port, for example (cf. below). Could you explain if it’s OK for vTaskSwitchContext to occur outside critical section? Regards. ~~~~ void vPortYield( void ) attribute ( ( naked ) ); void vPortYield( void ) { portSAVECONTEXT(); vTaskSwitchContext(); portRESTORECONTEXT();
asm volatile ( "ret" );
} ~~~~

Question about taskYIELD()

This is a VERY old thread and VERY specific to the FreeRTOS port. In the AVR portSAVE_CONTEXT() disables interrupts so vTaskSwitchContext() is protected.

Question about taskYIELD()

OK, I see that interrupts are disabled at the beginning of portSAVE_CONTEXT (cli instruction, I guess). So in general ports, interrupts should be (re)disabled around start of vPortYield, and not assume that they are already disabled?

Question about taskYIELD()

Each port has a different mechanism for yielding to a different task, and each case has to be considered on its own. More often than not, yielding is done using a standard or software interrupt, in which cases the hardware will either itself disable interrupts on interrupt entry, or otherwise the interrupt priority mechanism and/or asm code is used to manage interrupt nesting to ensure the context switch can occur cleanly. Also, some ports can/must yield in a critical section and the RTOS must save/restore the critical section nesting as part of the task context, while other ports (Cortex-M and RX for example) can’t possibly yield from a critical section. You are looking at a very basic port (as its a basic microcontroller), in which yielding is performed using a function call, and in that case interrupts are disabled manually. This is not really a critical section – the RTOS manages the yield, so is responsible for ensuring interrupts are left in the correct state when a task starts to run.