Precedence, if any, between vTaskSuspend() and taskNotifyWaitIndexed()

Hi, I couldn’t find another topic that could answer my query hence this post.

Background 1: In my system I have multiple applciaiton tasks and one “TaskManager” task. The task manager task, as the name suggests, manages other application tasks in certain ways and one of them is to enter low power mode. Now, due to architectural reasons, I cannot do low power centric operations/preparations in each of the application tasks and hence this manager task does some of it.

Backgroud 2: The application tasks inter-communicate using the Task notification mechanism and thus “block” on calls like taskNotifyWaitIndexed() for a notification or timeout.

Now in the “TaskManager” task, I need to suspend all applicaiton tasks using vTaskSuspend().

My questions are:

  1. what happens when vTaskSuspend() is called from the “TaskManager” task on an applicaiton task which was already blocked on a taskNotifyWaitIndexed() (from its own context, i.e. task function). Does the task move from blocked state to suspended state? As per the task state diagram on the FreeRtos website, I would assume so.
  2. If my assumption in 1 is correct(state = suspended), then, what will happen if a notify signal comes to this suspended task? Again, I would assume it remains suspended as per the task state diagram. And only a call to vTaskResume() will bring it out of the suspended state.
  3. If my understanding in 2 is correct, then, I have another question. Let’s say my application task was in blocked state due to a call to xTaskNotifyWaitIndexed()from its own context and then later in time, my “TaskManager” task calls vTaskSuspend() on this task. So now we know, that the tasks is in suspended state. All good! Now after some more time, lets say that the TaskManager task calls vTaskResume() on this application task and within this timespan, there was no notification sent to it. Then, my understanding is that the task will be brought to ready state which means it will execute on the next chance. Now, this is a bit wrong as in my opinion, the task should still be blocked on the xTaskNotifyWaitIndexed() call. But there is no API to explicitly set task state right?
  1. Yes - the task is removed from either the ready or blocked state here, removed from any even lists here, and then added to the suspended task list here. Task notifications are suppressed here.

  2. A task which is suspended will remain suspended regardless if a task notification is sent. The suspended, receiving task will note the reception of the notification but will not become unblocked as the task notification state bank is set to not wait for notifications when the suspend call is made.

  3. Your understanding is correct - a task resumed through vTaskResume will be placed in the ready state and will execute when it can. You’d need to perform a check to verify the task received a notification or not which can be done by checking the notification state of the task. This example, while not perfectly aligned, may give you some ideas.

1 Like

I do have a few questions about the design of your application…

  1. Could the application state instead ready all tasks for suspension and then use vTaskSuspendAll/xTaskResumeAll instead of suspending tasks one by one?
  2. How is suspending the task providing large power savings over simply leaving it blocked on the notification?
  3. And if the energy savings are meaningful, is your application tolerant to any delay in receiving task executing? If the task is suspended for a long period of time then the task notification may have significant delay.

It is generally not a good idea to suspend/resume task. If you describe what are you trying to achieve by suspending, we can try to see if there is a better solution possible.