Resume task from the beginning (Restart)
Hi,
I have a state machine where a task_manager controls the execution of different tasks, and suspends/resumes them according to the current state. When I resume a task, it continues from the same instruction where it was when it was suspended, as it is expected.
However, I have a task that reads and process data from a sensor and I need that every time the task is resumed it jumps back to the beginning of the for loop instead of continuing with its next instruction, in order to reset the variables to their initial values. Otherwise, when it is resumed it would carry on with the old values from the previous iteration, which would lead to wrong data.
Reviewing the FreeRTOS forum and StackOverflow I have found similar questions, with three possible near solutions, still not clear to me:
1.- Add a reset flag and check it regularly through the code or at the beginnning of the loop, as in:
https://stackoverflow.com/questions/38013728/how-restart-task-in-freertos
https://www.freertos.org/FreeRTOSSupportForumArchive/May2008/freertosHowtorestartthetask2034658.html
Checking the flag at the beginning of the loop as in this two previous links doesn’t fit for my solution, as there will be several instructions that will still be executed before the condition is checked again, creating errors.
On the other hand, checking the flag regularly through the code would imply doing it almost before every line of code (and I have 500+), and I guess there must be a more efficient way.
2.- Call vTaskDelete and vTaskCreate again for that function. I’m not sure if this will create memory fragmentation problems, as the task might be resumed many times.
3.- Call vTaskCreate for that function to use the same stack and TCB and reset its values to the initial state.
Is there another direct and safe way to tell the resuming task that it should start at the beginning instead where it was? If not, which of this three options is the most appropiate?
Many thanks in advance,
Álvaro
Resume task from the beginning (Restart)
The best answer is that using suspend/resume is the wrong tool. I would have that task check a flag to see if it is supposed to keep running just before doing the reading, and if not block (on a semaphore or direct to task notification) until it is needed. You can also include occational other checks to see if the processing it is doing is still needed, and if not go back to that first check. (This is basically the first option you listed). You probaly want to check each time before communicating to another task or maybe inside some long processing loop (if it has one).
WHY do you need it to immediate stop? (you comment on testing 500+ places), to me that seems to imply a poor problem description, and an inherent race condition in your specifications.
The biggest issue in my mind to using vTaskDelete/vTaskCreate is that if the task aquires any resources, those will be lost if the task is deleted, unless you do something to keep track of all of them. It is also a somewhat expensive operation.
Resume task from the beginning (Restart)
Thanks for your prompt and clear reply Richard,
I see, it is true that in this case suspending is not adequate. Instead of that, I will try making the task_manager set the flag and check before the reading, conjoined with occasional checks. If the task is not supposed to be running, I can reset the variables then and block on a semaphore, so it will be ready for the next time.
Yes, probably there is no need to stop it inmediately if I check before any relevant actions, I was just thinking about the ideal case in which no unnecesary instructions are executed.
Thanks a lot,
Álvaro