-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
I describe the full issue here: https://forums.freertos.org/t/multicore-smp-rp2040-port-deadlock-when-using-heap-3/19255/
In summary, FreeRTOS heap_3 calls vTaskSuspendAll which grabs the task lock before calling malloc/free. At the same time, if another task is using good-ol' malloc/free, a race takes place. Under FreeRTOS, the rp2040 port uses some macro magic to inject FreeRTOS support into the mutex functions. This implementation tries to grab the task lock also. heap_3 takes the FreeRTOS task lock before grabbing malloc_mutex, while a normal call to malloc takes the core synchronization spinlock first before grabbing the FreeRTOS task lock. This leads to a deadlock between the two tasks.
For clarity, let's say core 0 is calling into FreeRTOS heap_3, and core 1 is calling malloc (which is wrapped by pico-sdk). This is the sequence of events:
core 0:vTaskSuspendAllinvPortFreebefore callingfreecore 1: callsmalloccore 1: inmutex_enter_blockingwithmalloc_mutex, grabs core synchronization spinlockcore 0callsfreecore 0: inmutex_exitwithmalloc_mutex, blocks waiting for core synchronization spinlockcore 1: callslock_internal_spin_unlock_with_waitwhich is a macro provided by FreeRTOS rp2040 portcore 1: tries to grab task lock with an eventual call tovTaskEnterCriticalafter macro hell- deadlock,
core 1is holding onto the core synchronization spinlock,core 0has the task lock.
This happens because FreeRTOS heap_3 is trying to be multi task safe, but the pico-sdk's malloc and free wrappers are already providing this. I don't know of a good way to fix/clean this up, as it will likely need better cooperation between the rp2040 port and FreeRTOS itself.
My current workaround is to waste more SRAM and just use heap_4 and let FreeRTOS manage its own heap for its own objects, and let tasks use the "regular" heap that uses pico-sdk locking.