RTOS Task Execution Order with Equal Priorities

RTOS Task Execution Order with Equal Priorities: This question has puzzled many beginners. Today, I will briefly describe it with examples.

What is RTOS Task Priority?

In an RTOS, each task is assigned a priority. Among all ready tasks, the task with a higher priority executes first.

When we create a task, we need to assign (set) a priority value, for example, in FreeRTOS when creating a task:

/* APP task priority */#define APP_TASK_PRIORITY         6
/* Create application (APP task) */xTaskCreate(APP_Task, "APP_Task", 128, NULL, APP_TASK_PRIORITY, NULL);

6 represents the priority of the APP_Task (defined as 6), in the FreeRTOS system, the larger this number, the higher the priority.

However, not every RTOS follows the same rule where a larger priority value means a higher priority; some RTOS systems are the opposite.

For example, in UCOS, a smaller priority value means a higher priority.

What happens when two RTOS tasks have the same priority?

In the FreeRTOS system, if two tasks have the same priority (value), which one executes first?

Let’s describe this with code and experimental observations.

1. Create two tasks with the same priority

For example: APP_Task1 and APP_Task2, both with a priority of 6.

#define APP_TASK1_PRIORITY        6                        // APP task 1 priority
#define APP_TASK2_PRIORITY        6                        // APP task 2 priority
xTaskCreate(APP_Task1, "APP_Task1", 128, NULL, APP_TASK1_PRIORITY, NULL);
xTaskCreate(APP_Task2, "APP_Task2", 128, NULL, APP_TASK2_PRIORITY, NULL);

2. Two applications

For example: both increment a value and print the accumulated value at intervals.

static uint32_t Task1_Cnt = 0;
static uint32_t Task2_Cnt = 0;
static void APP_Task1(void *pvParameters) {  vTaskDelay(100);
while(1)  {    Task1_Cnt++;
if(0 == (Task1_Cnt % 1000000))    {printf("Task1_Cnt=%d", Task1_Cnt);    }  }}
// Author: strongerHuang
static void APP_Task2(void *pvParameters) {  vTaskDelay(200);
while(1)  {    Task2_Cnt++;
if(0 == (Task2_Cnt % 1000000))    {printf("Task2_Cnt=%d", Task2_Cnt);    }  }}

3. Experimental observations

Values are printed alternately, as shown in the figure below:

RTOS Task Execution Order with Equal Priorities

From the experimental observations, you can conclude:In FreeRTOS, two tasks with the same priority are scheduled in a time-slicing manner, meaning they execute alternately.

Of course, there is a prerequisite: the tasks must be in a ready state. If a task is in a blocked state, it will not be scheduled for execution.

For example: if a system delay (blocking) is added in task 1, then task 1 will not be executed. See the experimental observation in the figure below:

RTOS Task Execution Order with Equal Priorities

Additional Notes

The above discussion is specific to the FreeRTOS real-time operating system and does not apply to all RTOS.

For instance, UCOS2 behaves differently; when creating two tasks with the same priority, only the first (the one created first) is executed, while the second will not be executed.

Again, let’s look at similar source code and experimental observations.

1. Create two tasks with the same priority

Similarly: APP_Task1 and APP_Task2, both with a priority of 6.

#define TASK1_PRIO                             6
#define TASK2_PRIO                             6
/* Create task 1 */OSTaskCreateExt((void (*)(void *)) APP_Task1,                (void           *) 0,                (OS_STK         *)&Task1_Stk[TASK1_STK_SIZE-1],                (INT8U           ) TASK1_PRIO,                (INT16U          ) TASK1_PRIO,                (OS_STK         *)&Task1_Stk[0],                (INT32U          ) TASK1_STK_SIZE,                (void           *) 0,                (INT16U          )(OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR));
/* Create task 2 */OSTaskCreateExt((void (*)(void *)) APP_Task2,                (void           *) 0,                (OS_STK         *)&Task2_Stk[TASK2_STK_SIZE-1],                (INT8U           ) TASK2_PRIO,                (INT16U          ) TASK2_PRIO,                (OS_STK         *)&Task2_Stk[0],                (INT32U          ) TASK2_STK_SIZE,                (void           *) 0,                (INT16U          )(OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR));

2. Two applications

Again: both increment a value and print the accumulated value at intervals.

static uint32_t Task1_Cnt = 0;
static uint32_t Task2_Cnt = 0;
void APP_Task1(void *pvParameters) {  OSTimeDly(100);
while(1)  {    Task1_Cnt++;
if(0 == (Task1_Cnt % 1000000))    {printf("Task1_Cnt=%d", Task1_Cnt);    }  }}
// Author: strongerHuang
void APP_Task2(void *pvParameters) {  OSTimeDly(200);
while(1)  {    Task2_Cnt++;
if(0 == (Task2_Cnt % 1000000))    {printf("Task2_Cnt=%d", Task2_Cnt);    }  }}

3. Experimental observations

Only the first created task (Task1) prints values, as shown in the figure below:

RTOS Task Execution Order with Equal Priorities

So, why does this happen?

The answer is:UCOS2 does not allow tasks with the same priority (though UCOS3 does support this).

If a task of a certain priority (like 6) has already been created, attempting to create another task of the same priority (6) will fail. Here you can find the kernel source code:

RTOS Task Execution Order with Equal Priorities

Therefore, not all RTOS allow the creation of two tasks with the same priority; it depends on the specific RTOS.

Finally, do you understand now?

RTOS Task Execution Order with Equal Priorities

———— END ————

Leave a Comment