Do I have to suspect that a task can be interrupted at any time?

What are the rules for sequencial consistency between tasks? Do I have to assume that instructions from lower priority task could potentially always be interrupted by a higher priority task OR only if the lower prio task enters the blocking state?

Compare the following:
I have two tasks, one creates the other. But I don’t know how far the higher priority task proceeds until instructions from taskB are executed. Will taskA or B finish first? In case taskA finishes first, this would leave taskB with the problem that the semaphore is in an undefined state…

static SemaphoreHandle_t shared_sem;

taskA()
{
    xSemaphoreTake(shared_sem);
    // .. do something non blocking
    xSemaphoreGive(shared_sem);
    vSemaphoreDelete(shared_sem);
    vTaskDelete(NULL);
}

// taskB runs with priority of 10
taskB()
{
    shared_sem = xSemaphoreCreateMutex();
    xTaskCreate(&taskA, "taskA", 8 * 1024, NULL, 15);

    xSemaphoreGive(shared_sem);

    // do something..
    // is it possible that we're interrupted by taskA here or not?

    // now we want the semaphore!
    xSemaphoreTake(shared_sem);
    // Could taskA be deleted in the meantime???
    // then the following would result in an error!
    xSemaphoreGive(shared_sem);
}

I just have difficulties wrapping my head around this :confused:

First I’d not recommend to dynamically create/delete shared resources and also tasks as it increases complexity and might cause subtle bugs.
A higher prio task always preempts lower prio tasks if it gets ready to run (and if the default preemptive scheduling scheme is used/configured).
BTW this has nothing to do with sequential consistency of (task) C-code as defined by the standard.

Thanks! Does this mean that it’s good practice to create ALL tasks at the start of the program (in a modules init function maybe)? How about deleting them? Would you use a cleanup function to delete the tasks at the end of the program or just let the kernel do it for you?

“Do I have to suscect that a task can be interrupted at any time?”

Am I correct in assuming that your answer to this would be a yes then?

Interleaving behavior is dependent on the options you give In your config.

Normally, with preemption turned on, any task can be interrupted at any point (except inside critical sections) by a higher priority task.

You can turn preemption off, and make FreeRTOS a ‘cooperative’ system, and in that case context switches will only occur at calls to FreeRTOS operations. This may make things a bit easier to avoid race conditions, but greatly impacts the ‘Real Time’ performance of the system, as High Priority tasks are now contained by the performance of a possible low priority task not reaching such a point often enough.

As Hartmut says, dynamically creating and destroying resources isn’t normally the best practice, and you should only destroy resources after you KNOW that no one else will try to access them anymore.

That makes sense! I didn’t know that the interrupt can’t happen in between critical sections though. Does this mean a task holding a mutex can’t be interrupted?

No. Richard was talking about critical sections which are a special tool. See e.g. This page describes the FreeRTOS taskENTER_CRITICAL() and taskEXIT_CRITICAL() API macros.
Tasks holding a mutex can be interrupted, of course.

As Hartmut said, a ‘Critical Section’ is the piece of code between a call to taskENTER_CRITICAL() and a matching call to taseEXIT_CRITICAL() and during that period no interrupt that can interact with FreeRTOS can occur, which means it really needs to be kept short.

There is an alternate, slightly weak, form, between calls of vTaskSuspendAll() and vTaskResumeAll() which allows interrupts, but no interrupt can initiate a task switch. Care needs to be taken with this, as that will impact the Real Time responce for all higher priority tasks.

It still doesn’t solve the issue of deleting a resource that other tasks might access afterwords.

Thank you both for the explanations. I was not aware about the critical sections API and the appliances of vTaskSusependAll(), so that really helped my knowledge.

I guess the problem with deleting resources that other tasks might still need is due to design faults alone. I guess I need to restructure my system so that the access of resources is always passed thorugh an API that checks if the task is still running.

Checking that the task is still running is unreliable, as you need to make sure that things don’t change between the time you make the check and when you act.

The real answer is you shouldn’t remove a resource unless you KNOW that no one else could be using it anymore.

Personally, I find that I rarely am dynamically creating and deleting resources. You may need to think about what you are doing, and why you are wanting to do what you are doing.