Another source of latency

Hi
While searching for crash I thought that maybe malloc/free is not protected by mutex and discovered vTaskSuspendAll in pvPortMalloc.

Why not mutex?

void *pvPortMalloc( size_t xWantedSize )
{
BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink;
void *pvReturn = NULL;

  **vTaskSuspendAll();**

Rasty

Mutex support requires much more code and the heap an additional init function (statically) creating the mutex. Also assuming the lock time is very small it might not be worth it or acceptable for others. On the other hand if you think you need it, it’s fine to use your own heap using a mutex.

One big problem is the danger of Deadlock.

What can happen is one task can start a memory allocation, where it takes the mutex. Then while that operation is running, the system switches to another task.

That task then either suspends the scheduler or enters a critical section and tries to do a memory alloction. It will try to take the mutex, but be blocked, but because of the current condition, the system isn’t allowed to change to a different task, and we are deadlocked.

That’s indeed an important point. I’d say taking a blocking lock inside a critical section or with scheduler suspended is a (fatal) bug along with dynamically allocating memory in that situation without knowing the internals of the memory manager (if it’s supported or not).
However, using a mutex here would add a certain amount of complexity and could make user applications more error prone.

Yes, and since memory acquisition is a fundamental operation, restricting the application state when you can do it is error prone. The Scheduler suspend has the advantage that it is a “Can not fail” operation that (if you follow the rules) is deadlock free, makes it suitable for the task.

what bothers me is not dead-lock. It can be prevented by priority inheritance, rather hard-to-understand real-time problems due to dynamic memory allocation/free from low-priority tasks.
Last thing that I’d expect is critical section protecting large code, which may have non-deterministic behavior.
It is normal to have dynamic memory allocation in embedded code, which is not on critical path.

The problem is that priority inheritance does NOT fix the deadlock, as the case I was pointing out was doing a memory allocation inside a Scheduler Suspension block (a form of critical section). Unless you place a global design requirement that NO memory allocation can occur with the scheduler suspended (or in a critical section), which is a requirement that FreeRTOS does NOT impose, a mutex protection can have that sort of problem.

If you can impose that limitation on your code, then you can define your own protection based on a mutex.

1 Like

I generally do agree on that point. @richard-damon and I have been discussing this issue vehemently in the past. While I generally prefer to go for the finest granularity of thread-of-execution-lock possible, I can see arguments for the other side in certain scenarios as well.