Hybrid Scheduling

huzhiping wrote on Thursday, December 19, 2013:

Does anyone have an example of hybrid scheduling that preemptive and cooperative scheduling can coexist in the same system?

What I want to do is that my system have several tasks running, one of them is the system check periodically in 1 or 2 second like RAM/ROM check…, I want it to be preemptive which is running in the back with lowest priority except idle task, the other tasks have the normal function with higher priority, I want them to be co-opertive.

the realtime kernel book has a short description for it, but didn’t provide more details. I don’t know if it is possible that both scheduling can coexist in the same system.

Thanks in advance!


rtel wrote on Thursday, December 19, 2013:

The kernel can only be set up in one way in any one build - so all the tasks within the same build use the same scheduling policy. So you can’t set a scheduling policy per task.

If I understand your post correctly you want the low priority tasks (Idle and RAM/ROM checker) to be preempted by the higher priority tasks, but for the higher priority tasks to co-operate. Presumably you therefore mean that the higher priority tasks will not time slice.

You can effect something like this by setting configUSE_PREEMPTION to 1, and configUSE_TIME_SLICING to 0. Then the lower priority tasks will not time slice either, but will be preempted by the higher priority tasks.

If you want the lower priority tasks to share CPU time they can call taskYIELD() manually within their implementations.

Likewise the higher priority tasks. The scheduler will switch between the higher priority task, but not just because a tick interrupt occurred. The scheduler will only switch from one task to another because the task either manually called taskYIELD(), or it performed an action that invoked the scheduler (such as posting to a queue on which another task was blocked).


dragonflight1 wrote on Thursday, December 19, 2013:

If you want to run the higher priority tasks co-operative as a means of controlling mutual exclusion, be aware that the scheduler will switch between the tasks if an interrupt performs a task that invokes the scheduler i.e. you MUST NOT include

    if( xHigherPrioritytaskWoken == pdTRUE )
        portYIELD_FROM_ISR(); /* or portEND_SWITCHING_ISR() depending on the port.*/

in you interrupt routines if they call any xxxFromISR FreeRTOS functions

In addition the scheduler will switch processes (once) as a result of any timeout in the high level processes (such as vTaskDelay or a timeout in a send/receive and not necessarily to the task that triggered the timeout. see https://sourceforge.net/p/freertos/discussion/382005/thread/278999da/ for a thread on configUSE_TIME_SLICING.

IMHO, if you want to use co-operative scheduling for your high-level processes you should use it everywhere and merely call taskYIELD() liberally in the low-priority processes

huzhiping wrote on Thursday, December 19, 2013:

I probably only use co-operative scheduling in my system, in higher priority tasks use vTaskDelayUntil to make fixed period call, for example 10ms, in the lowest priority task (system check), call taskYIELD() in the end of the function like Mike said to force context switch.

In my higher priority tasks, I would like 2 or 3 tasks have the same priority and with time slicing since they have the same importance. But it looks like “configUSE_TIME_SLICING” only works with “preemptive” and not works for “co-opertive” scheduling, is this right? if this is true, is there a way to implement time slicing for the same priority tasks in co-operative scheduling?



dragonflight1 wrote on Thursday, December 19, 2013:


If I can be so bold, why do you want to use co-operative scheduling at all?

huzhiping wrote on Thursday, December 19, 2013:


Actually I am evaluating to see if FreeRtos can be used in my new project, this new project is based on a old project which using OSEK as RTOS and different Micro. OSEK can have preemptive and cooperative coexist in one system. In my previous project It has preemptive low priority system check task and higher priority tasks in cooperative scheduling, some of these higher priority tasks are safety related tasks, using preemptive scheduling will interrupt some safety tasks when running. we only allow the “system check task” to be able to be interrupted by higher periority task. I don’t want to change them too much.



dragonflight1 wrote on Thursday, December 19, 2013:

IMHO, if you want to perturb the old project as little as possible I would stick with co-operative which means you don’t want time slicing. Time slicing would interrupt your “safety tasks”. Your other main concern is that when designing co-operative tasks you have mutual exclusion between tasks, except at the control points. Switching to preemtive/time slicing would require careful examination of the tasks to determine possible race conditions, resource sharing, non-reentrant functions (e.g. sprintf on PIC24’s is non-reentrant), etc.

PS. according to RTEL in https://sourceforge.net/p/freertos/discussion/382005/thread/278999da/ (thread on configUSE_TIME_SLICING), it is only after 7.6.0 that co-operative scheduling guarantees control of process switching (don’t know the behaviour prior)