1

I am learning about mutex and semaphore. And got a quick question to clarify:

void task1(void* parameter){
    while(1){
        global_var++;
    }
}


void task2(void* parameter){
    while(1){
        global_var++;
    }
}

    xTaskCreate(task1,"task1",10000,NULL,1,NULL); // receiving modem input
    xTaskCreate(task2,"task2",10000,NULL,1,NULL); // receiving modem input

If I have 2 tasks that are accessing one global variable. Is there a possibility if one task will interrupt another task if both are the same priority? Or the issues only start happening when one command is different priority or the task is being interrupted via the timer or other interrupts?

TheBestPlayer
  • 324
  • 2
  • 13

2 Answers2

1

The tasks are getting scheduled by the operating system (f.e.: freertos). It depends on which scheduling technique is used. If it uses Round-Robin, the tasks are scheduled fairly, which means task2 will be scheduled after (defined timeslice) task1. Which means no starvation.

But as you mentioned if there is a interrupt, the ISR will be executed instead of task1 or task2.

A example can be found on: freertos page

There are two sheduling policies: FreeRTOS kernel supports two types of scheduling policy: Time Slicing Scheduling Policy: This is also known as a round-robin algorithm. In this algorithm, all equal priority tasks get CPU in equal portions of CPU time. Fixed Priority Preemptive Scheduling: This scheduling algorithm selects tasks according to their priority. In other words, a high priority task always gets the CPU before a low priority task. A low priority task gets to execute only when there is no high priority task in the ready state. (from https://microcontrollerslab.com/freertos-scheduler-learn-to-configure-scheduling-algorithm/)

You can select scheduling algorithms by setting corresponding configuration bits (flags/defines) in theFreeRTOSConfig.h file.

For synchronization you should use a mutex (SO answer mutex). As wovano said semaphores are not exactly the same as a mutex (see semaphores vs. mutex).

Kraego
  • 2,978
  • 2
  • 22
  • 34
  • I see thank you. So task1 and task2 will run without any issues if both tasks have same priority and no interrupts are happening with the default FreeRTOS scheduling techinque (round-robin). If tasks have different priority levels or interrupts are used to access the same global variable, then mutex or semaphore shall be used. Is that correct? – TheBestPlayer Sep 29 '21 at 07:04
  • Yes that's basically it. I've updated the answer and added synchronization part (mutex, semaphores). – Kraego Sep 29 '21 at 07:31
  • Well copied from my answer ;-) But the conclusion is not correct. "_If tasks have different priority levels (...) then mutex or semaphore shall be used._" No, a mutex should be used if different tasks or interrupts are accessing the same resource, *also when both tasks have the same priority*. – wovano Sep 29 '21 at 07:54
  • And this may be nitpicking, but a mutex does not "avoid being interrupted". Even when having a mutex, a task can be interrupted (by interrupts as well as by other tasks, even with the same priority). However, it solves the problem of possible data corruption. – wovano Sep 29 '21 at 07:55
  • 1
    IMHO, priority inversion is an interesting topic, but a little bit out of scope of this question (and may only confuse the OP). Priority inversion is handled/avoided by FreeRTOS very well, as long as you use the right structures (so in this case: a mutex, not a semaphore). – wovano Sep 29 '21 at 07:56
0

Yes, both tasks will be scheduled alternately and thus can "interrupt" each other. By default, the tasks will be switched every millisecond.

Since both tasks share a resource (the global variable) and the increment operation is (in general) not atomic, you should indeed use a mutex to prevent possible errors.

NB: A mutex is not the same as a semaphore. Since you want MUTual EXclusion in this case, a mutex is the right solution.

(Note: this is only true if FreeRTOS is configured to use preemptive scheduling with time slicing, i.e. configUSE_PREEMPTION == 1 amd configUSE_TIME_SLICING == 1, which is the default.)

wovano
  • 4,543
  • 5
  • 22
  • 49
  • Thank you for explaining. Let me clarify this once again. This is only true when task1 and task2 have different priorities right? If task1 and task2 have same priority levels, the tasks will execute one after another without interrupting each other without interrupting each other. However, if tasks have different priority levels , the MUTEX should be used to ensure the correct behaviour – TheBestPlayer Sep 29 '21 at 06:59
  • @TheBestPlayer, no it's exactly the opposite. If tasks have different priorities, the lower priority task will only run when the higher priority task is idle. In your example code, that will never be the case, since the `while(1)` loop never stops. So only one task will run. If both tasks have the same priority, FreeRTOS will periodically "pause" one task to let the other one run. The exact moment when that happens is unknown (it could be just after having incremented the number but before writing it back to memory). – wovano Sep 29 '21 at 07:13
  • @TheBestPlayer NB: I'd recommend to read the [documentation of Tasks](https://freertos.org/taskandcr.html) and possibly more, on the official webpage. IMHO, FreeRTOS is a very nice OS with great documentation. You'll learn a lot when browsing through the site and reading about the topics you're interested in. Multithreading is quite a challenging but interesting topic, I think :-) – wovano Sep 29 '21 at 07:18
  • I think I got it now. If time slicing is turned ON, the tasks with equal priority will share the CPU time and get interrupted by each other. The behaviour that I have initially explained(Equal priority tasks running one after another) would be only true if time slicing is turned OFF, is that correct?. Thank you very much for help. I will read more about it – TheBestPlayer Sep 29 '21 at 07:46
  • @TheBestPlayer According to the [documentation](https://www.freertos.org/a00110.html#configUSE_TIME_SLICING), "_If configUSE_TIME_SLICING is set to 0 then the RTOS scheduler will still run the highest priority task that is in the Ready state, but will not switch between tasks of equal priority just because a tick interrupt has occurred._" I personally don't have experience with this setting (time slicing disabled), but I don't think it means that "equal priority tasks will be running one after another". I think they can still be switched, but not due to the timer tick. – wovano Sep 29 '21 at 08:20