Tasks: Management of custom dynamic memory

Hi,

I’m looking for a way to pass custom allocated dynamic stack memory to a FreeRTOS task, like in xTaskCreateStatic(), but it should be deleted automatically in prvDeleteTCB().

The reason we need this is that we keep getting requests for pthreads with stack memory on external RAM in the ESP-IDF pthread implementation. ESP-IDF’s pthread library, which is basically implemented on top of FreeRTOS, similar to FreeRTOS-Plus-POSIX. xTaskCreate() uses pvPortMallocStack(), which is hard to customize for this purpose since it only takes the size as argument.

I already considered following approaches:

  • using xTaskCreateStatic() and portCLEAN_UP_TCB(): This does not work due to the implementation of prvDeleteTCB(), which still accesses the TCB after calling portCLEAN_UP_TCB()
  • using xTaskCreateRestricted() and portCLEAN_UP_TCB(): This might work, but according to the documentation, xTaskCreateRestricted() should only be used “in systems that include an MPU implementation”
  • Using xTaskCreateStatic() and portCLEAN_UP_TCB() and Changing prvDeleteTCB() to copy relevant members of the TCB to local variables so both stack and TCB can be deleted by portCLEAN_UP_TCB(): This would involve changes in FreeRTOS itself and we would not like to divert if we are not sure if the change can be upstreamed.
  • Possibly making ucStaticallyAllocated of the TCB more general and add another task create function, but that would be a substantial change, I guess. Similar problem as above.

Is there any other possibility to achieve the goal of having custom dynamic memory or did I miss something? If not, what would be the best of the solutions provided above?

Any links have been omitted because I’m a new user

Thanks!

If the allocator is only for the stack, can you provide your own implementation of xPortMallocStack() and vPortFreeStack()? These default to xPortMalloc() and vPortFree() if configSTACK_ALLOCATION_FROM_SEPARATE_HEAP is undefined or defined as 0, and are only used to allocate and free the stack if configSTACK_ALLOCATION_FROM_SEPARATE_HEAP is defined as 1.

Relevant references:
https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/V10.5.1/tasks.c#L763
https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/V10.5.1/tasks.c#L3976
https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/V10.5.1/include/portable.h#L183

Hello, thanks for the answer! We haven’t upgraded our FreeRTOS to a version including xPortMallocStack(), so I missed these. They are probably closest to what we need so far. But the problem we face is that we want to be able to selectively place some of the created FreeRTOS task stacks in a different memory region, the rest needs to stay in the “default” region. Hence, we need a way to signal this to xPortMallocStack(), which is impossible at the moment because it has only one argument: the requested size of the stack. There are probably ways around this using any kind of global context information, but this will become really tricky if a higher priority task is preemting the original task and also tries to create a task.

Perhaps the best option for custom stack allocation is to create the task with xTaskCreateStatic (and enable static memory allocation). Then you can just create the stacks in the memory region you want.

Would adding a second macro, something along the lines of portCLEAN_UP_MEMORY(), somewhere around here help? If so feel free to create a PR to do that - although we would have to agree on the new macro’s name. The “port” on portCLEAN_UP_TCB means it is in the port layer (I think this was added for TriCore targets that aren’t stack based), which in turn means the port in use always calls that macro when the containing function gets called. You’re use case sounds more selective, so it might be a “config” macro.

@rtel

Would adding a second macro, something along the lines of portCLEAN_UP_MEMORY()

I’m try the addition of a macro right now. I would like to test it first to be 100% sure that this works for all our cases before creating a PR.

@richard-damon

Perhaps the best option for custom stack allocation is to create the task with xTaskCreateStatic (and enable static memory allocation). Then you can just create the stacks in the memory region you want.

This works in some cases. However, the problem is that we would like to have a mechanism to automatically free memory once tasks are deleted. This is important for higher-level APIs such as pthread, which in turn might be used by other libraries not written with this special kind of memory management in mind.

Without any modification to the kernel, I currently don’t see any possibility for notification that the corresponding stack memory of a task can be free-ed. Unless I missed something, in which case I’d be happy to hear alternatives.