Task Pools

tomwbarclay wrote on Tuesday, June 28, 2016:

I am looking at V9 with the aim of creating task pools for re-use in RAM limited real time systems. The idea is to statically create empty tasks at boot time then have a master task populate them depending on the device operating mode. No malloc-free memory heap is allowed.
My nitial thought is to provide a standard pool interface such as task_pool_request_task method and have it allocate a TCB and stack along with a task_pool_return_task method to hand back the resources once it is no longer required.
There seem to be a number of issues - questions.
a) the request method creates (statically) a task but note that the task handle is NOT unique to the executable code function as it is essentially a pointer to the TCB, which is shared among a number of potential code functions…
b) The TCB contains the link list elements for the task management so the kernel must guarantee that all these items have been removed from the kernel control lists before the TCB resource can be re-used. This is achieved by the task delete function. I am not sure that this can be checked externally in the application. If a task offers itself for deletion it is not deleted immediately but placed on the pending queue to be deleted next time the idle task is run.
So the question is are there any other issues ??? The pseudo code is below …

task_pool_request_task
get_free_task_TCB_and_STACK // get one of the RAM blocks allocated at boot time
create_task // standard FreeRTOS static task creation
suspend_task // task will be started by high level mode control task
end

task_pool_return_task
delete_task // standard FreeRTOS task deletion
return_free_task_TCB_and_STACK // hand back RAM block
end

Any comment or hints would be appreciated.

FYI … I am developing on Atmel Studio7 for SAM4N uP

rtel wrote on Tuesday, June 28, 2016:

I am looking at V9 with the aim of creating task pools for re-use in
RAM limited real time systems.

In my experience, and in the general case, RAM limited real time systems
rarely create and delete many tasks at run time. Rather they create all
the resources during initialisation, then those resources perform a
dedicated task and persist until the system is switched off.

Of course there are some application that fall outside of that
generalised case.

a) the request method creates (statically) a task but note that the
task handle is NOT unique to the executable code function as it is
essentially a pointer to the TCB, which is shared among a number of
potential code functions…

I’m not sure why that is an issue, but perhaps it is because you don’t
know if the task has changed between two subsequent reads of the task
handle - because the handle will be the same if the task is using the
same StaticTask_t object from your pool.

This has also been an issue for kernel aware IDE plug-ins. The issue
was solved by also giving each task a unique number. You will see the
uxTaskNumber variable is incremented each time a task is created or
deleted - it is incremented when a task is deleted so the kernel aware
debugger knows it has to re-read the task list. The variable is stored
inside the task’s TCB, but [by default] is not accessible - but could be
made accessible.

b) The TCB contains the link list elements for the task management so
the kernel must guarantee that all these items have been removed
from the kernel control lists before the TCB resource can be re-used.
This is achieved by the task delete function. I am not sure that this
can be checked externally in the application. If a task offers itself
for deletion it is not deleted immediately but placed on the pending
queue to be deleted next time the idle task is run.

In version 9 that is only the case if a task deletes itself. If one
task deletes another task then the deletion occurs immediately. In
either case, when the TCB is actually deleted (perhaps conceptually if
you are only using static memory allocation) then the portCLEAN_UP_TCB()
macro will be executed. By default that is empty (I think) so you could
implement it in FreeRTOSConfig.h to return the TCB to the pool. Just be
careful to note that portCLEAN_UP_TCB() is called before the TCB is
access for the last time if dynamic memory allocation is used - but if
you are only using static memory allocation then that should be fine.

tomwbarclay wrote on Tuesday, June 28, 2016:

Thanks for your input. I dont think the task_handle non uniqueness will be an issue as I will make sure its not persistent beween mode switches. Also its relatively easy to make tasks signal a central task delete task so that no task ever deletes itsself. I was not aware about the debugger issues, so thanks for that.

If I find any wrinkles in implememntation I’ll re-post here …