ulTaskNotifyTake and vTaskSuspendAll

mastupristi wrote on Thursday, June 20, 2019:

I tried calling ulTaskNotifyTake(pdTRUE, portMAX_DELAY) after calling vTaskSuspendAll(); It happened that the ulTaskNotifyTake() returned immediately as per timeout.
Ok, after reading the vTaskSuspendAll() page I remembered I couldn’t do that. But I did get some questions:

  • If vTaskSuspendAll() suspends the scheduler but not the interrupts, why keep the RTOS ticks pending?
  • The behavior of vTaskSuspendAll() I wanted it to wait and exit after a call to vTaskNotifyGiveFromISR() from an interrupt. What I could expect was that an assert would be triggered due to an attempted context switch (caused by ulTaskNotifyTake) with a suspended scheduler. What happens is none of this. Is that correct?

The call to ulTaskNotifyTake() takes place inside a function called from other parts of the code, and for a sequence of events it can happen that this function is called with suspended scheduler. How can I get around the problem?

best regards
Max

rtel wrote on Thursday, June 20, 2019:

As a general rule API functions that can cause a context switch cannot
be called from a critical section or with the scheduler suspended as the
context switch cannot actually happen, which results in logic errors.
From your post I think you realise this already.

If a context switch is attempted from an interrupt then the context
switch should be held pending until such time that the scheduler is
unsuspended. That mechanism works by placing the task that was
unblocked into a ‘pending ready’ list, then moving all tasks from the
‘pending ready’ list into their appropriate ‘ready’ list in the
unsuspend function. It is not clear to me, but are you saying that
mechanism is not working in the case of a task notification?

mastupristi wrote on Friday, June 21, 2019:

On Thu, Jun 20, 2019 at 11:41 PM Richard Barry rtel@users.sourceforge.net
wrote:

As a general rule API functions that can cause a context switch cannot
be called from a critical section or with the scheduler suspended as the
context switch cannot actually happen, which results in logic errors.

what does it means by “logic errors”? Should this case be
reported/protected with configASSERT?

unsuspend function. It is not clear to me, but are you saying that

mechanism is not working in the case of a task notification?

I still don’t know what you mean.

for example:

vTaskSuspendAll();
uint32_t ulNotificationValue;
ulNotificationValue = ulTaskNotifyTake( pdTRUE, portMAX_DELAY );
if(0 == ulNotificationValue){ /* timeout expired */
break;
}

the call to ulTaskNotifyTake() exit immediately with 0 as returned value.
Is this the behavior you expect?

Is there an API to know if the scheduler is suspended?


Et nunc, auxilium solis, vincam!
Oppugnatio solaris!
VIS!

Massimiliano Cialdi
cialdi@gmail.com

richarddamon wrote on Friday, June 21, 2019:

Second question, see https://www.freertos.org/a00021.html#xTaskGetSchedulerState
xTaskGetSchedulerState tells you the state of the scheduler.

If the scheduler isn’t running, then a task can not block as that requires the sceduler to switch to another task to run. From the documentation of vTaskSuspendAll():

API functions that have the potential to cause a context switch (for example, vTaskDelayUntil(), xQueueSend(), etc.) must not be called while the scheduler is suspended.

So you code is breaking this rule.

rtel wrote on Friday, June 21, 2019:

Because of…

As a general rule API functions that can cause a context switch cannot
be called from a critical section or with the scheduler suspended as the
context switch cannot actually happen, which results in logic errors.

vTaskSuspendAll();
uint32_t ulNotificationValue;
ulNotificationValue = ulTaskNotifyTake( pdTRUE, portMAX_DELAY );

The above task cannot block because a context switch cannot happen.

the call to ulTaskNotifyTake() exit immediately with 0 as returned value.
Is this the behavior you expect?

So yes that is the expected behaviour.