Memory allocator - bget - mutual exclusion

anonymous wrote on Monday, September 06, 2010:

I would like to use dynamic memory allocation, other than supplied with Freertos. I decided to use the bget library. The allocator will be used by FreeRTOS, the lwIP TCP/IP stack and by application code. bget library functions must be protected against concurrent access. What should I use? I can not use a mutex, because he also is created dynamically (vicious circle). The file uses heap_3.c the following method:
vTaskSuspendAll ();
pvReturn = malloc (xWantedSize);
xTaskResumeAll ();
Is this a good or optimal solution of mutual exclusion? Maybe someone has already solved this problem?
Thanks in advance.

richard_damon wrote on Monday, September 06, 2010:

This seems a good solution for the task. As you have noted, using a mutex or similar adds the complexity of needing to create the mutex in the first place.

Another solution would be using a critical section (which disable interrupts), but memory allocation is a slow enough process that this may impact your interrupt response time excessively, but as I mentioned to someone else, would be needed if an ISR needed to allocate memory.

If you do want to use a mutex, it is possible to get around the recursion issue as follows (it requires a small change to kernel code)

First make xSchedulerRunning non-static, so you can access in your code (this is the only change to the kernel needed)

in your wrapper use code something like this (untested, and assumes INCLUDE_vTaskSuspend == 1, otherwise need to adjust the take)

xSemaphoreHandle mutex = 0;
extern volatile signed portBASE_TYPE xSchedulerRunning;
void *pvPortMalloc( size_t xWantedSize )
void *pvReturn;
    if( xSchedulerRunning)
        xSemaphoreTake(mutex, portMAX_DELAY);
        if(mutex == 0)
            mutex = xSemaphoreCreateMutex();
    pvReturn = malloc( xWantedSize );
    if( xSchedulerRunning) 
#if( configUSE_MALLOC_FAILED_HOOK == 1 )
        if( pvReturn == NULL )
             extern void vApplicationMallocFailedHook( void );
    return pvReturn;

This breaks the recursion, and gets the mutex allocated, by not using it before the scheduler is started, which is guaranteed to happen with the allocation of the idle task.

rtel wrote on Monday, September 06, 2010:

I have not studied this thread completely, so sorry if I miss the point.

Heap_2.c has a macro called prvHeapInit() in which the mutex could be created - should you decide to go that route.

The following links could be useful too:


richard_damon wrote on Monday, September 06, 2010:

The original poster was wanting to make a variant memory allocation function, and had a question about what the “best” exclusion method to use (like malloc, their function was not reenterant). They noticed that the existing heap functions used the xTaskSuspendAll()/xTaskResumeAll() and was wondering if this was a good method, they had been thinking of a Mutex, but of course, that runs into a chicken and egg problem that to create the mutex, you need to allocate memory but to allocate the memory you want the mutex (I showed one way to modify things to break this cycle).

I suppose it might make an interesting article to talk about other choices for memory management exclusion. The method used in the heap management functions with FreeRTOS are good for most applications, but I suppose some people want/need something different.

If someone need to use memory allocations inside ISRs then you need to switch to using critical sections for exclusion, which makes the exclusion work with interrupts, which is the primary advantage and disadvantage (since it means that interrupts get significantly additional latency),

The other direction could be to move to the mutex, This adds some complexity and overhead to the call (but still less than the allocation might take), but does have the advantage that if an interrupt does come by and activates a higher priority task, that task will start up right away (as long as the task doesn’t need to allocate an memory, if it does then the allocation interrupted will need to complete first).