Skip to content

Using FreeRTOS-Kernel-Heap3 library leads to deadlock across cores, race condition on core spinlock #1646

@gemarcano

Description

@gemarcano

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:

  1. core 0: vTaskSuspendAll in vPortFree before calling free
  2. core 1: calls malloc
  3. core 1: in mutex_enter_blocking with malloc_mutex, grabs core synchronization spinlock
  4. core 0 calls free
  5. core 0: in mutex_exit with malloc_mutex, blocks waiting for core synchronization spinlock
  6. core 1: calls lock_internal_spin_unlock_with_wait which is a macro provided by FreeRTOS rp2040 port
  7. core 1: tries to grab task lock with an eventual call to vTaskEnterCritical after macro hell
  8. deadlock, core 1 is holding onto the core synchronization spinlock, core 0 has 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions