Problem understanding vTaskDelete()

paulgcoleman wrote on Monday, March 12, 2012:

I need to delete a number of tasks and recreate them from a task which has a higher proirity than the idle task. I read in the manual that for vTaskDelete() to work correctly the idle task must be allows some CPU time as it is responsible for freeing the meory associated with the task being deleted. My question is how much time does it need? If I need to suspend my task to allow the idle task to run I need to make sure I do it for long enough but I don’t have any concept of how long that needs to be.

Thanks, Paul.

richard_damon wrote on Monday, March 12, 2012:

It takes very little time for the idle task to do its job, as it just repeatedly checks a list of tasks that need to be cleaned up, and do releases the memory for them. Of course the big issue is you need to make sure that no other tasks startup instead and use the time up. If you have enough space on the heap, you might not even need to wait, just grab the extra space and when the system is idle it will reclaim the space. One option is to just attempt to create the task, and if you get an error wait for 1-2 ticks and try again (repeatedly), hoping that eventually the idle task will get its chance to do the clean up and release the memory.

On a second note, deleting a task and then recreating it is not a normal sort of operation.  Normally it is better to just write the task to just go back and wait for instructions to start again. Be aware that deleting a task does NOT automatically return to the heap any memory allocated by that task (except the stack/tcb) or release any Semaphores owned by it, so you need to use care in deleting a task at a “random” time.  The one case where I can see deleting a task is where you at different times need different numbers of worker tasks for something, so you create them as needed and when they are done, they delete themselves or notify a central controller task that they are done.  Even in this case, it is often better to just create a given number of them and have them wait for work unless you need to be able to trade off heap space for task control to extra heap space to use for the tasks themselves doing their work. You just need to be VERY sure you watch for and handle out of memory conditions (if you have enough not to worry about, the thread pool works cleaner), and need to worry a bit about heap fragmenttion.

paulgcoleman wrote on Tuesday, March 13, 2012:

Thanks for the information.

The reason I was going down the route of deleting and re-creating the tasks was that I have 8 tasks which are basically motor controllers using state machines waiting on various semaphores and when an error occurs I need to be able to stop all the motors, recover the error and then restart the 8 tasks from a known state.

Regards, Paul.

richard_damon wrote on Tuesday, March 13, 2012:

I generally set up this kind of response by setting a flag for each task that cause the task to do the appropriate shutdown and restart procedure within the task. It is generally easier to add a “global abort” to a given task than to handle all the possible conditions of a task being abruptly and randomly terminated and restarted. Unless your abort routine has a lower priority than all the motion axes, you have no idea where the motion tasks are in their execution. Being lower, you at least know they are all in some form of a blocking state.

paulgcoleman wrote on Wednesday, March 14, 2012:

Thanks for the reply.

The problem I face is that the tasks can be in any one of a number of states within the state machine probably waiting on motors to finish moving a set distance. For some axes this could be a 15 second wait, during which the task is suspended waiting for a semaphore (which is give via an ISR at the end of the movement). Therefore it is very difficult to just tell a task to go to an error recovery state because it will probably be asleep.

richard_damon wrote on Wednesday, March 14, 2012:

If we can assume that the state machines only are waiting on semaphore/queue that are dedicated to motion operations (or at least these are the only thing that can delay them a “significant” time period), then the simple solution is after setting the “abort” flag for each task and then signal all those semaphores ending their waits. Then you test the flag at each wait and jump to the abort condition. This is basically writing the abort condition explicitly at each state rather than as just a “global asynchronous” signal. If you want one of the states to have a fixed delay, rather than use a vTaskDelay operation, you do a xSemaphoreTake operation on a semaphore that only is given in the case of an abort or at least won’t be given during the delay except via an abort.

As I said, the danger of just deleting a task and recreating it is you must then make sure that your tasks can never “own” resources at any time they might be aborted, including but not limited to heap memory, mutexes, and so uses of semaphores. Note that these sort of problems are very hard to test for, and often are hard to diagnose when they do pop up.