Is it safe to call vTaskNotifyGiveFromISR from outside an ISR?

I wish to execute the following pseudocode in a task context:


disable interrupts;
for (task : listOfWaitingTasks) {
  notify task;
}
enable interrupts;

if (a higher priority task than me was woken in that loop) {
  yield to the highest priority task that was woken;
}

My intention is that the highest priority task that was woken will get the CPU. What I don’t want is for the first task that had a higher priority than the caller to get the CPU, if there was a higher priority task later in the list.

I propose to do this by using vNotifyGiveFromISR in the loop to notify the task, then if any of those calls has set the higherPriorityTaskWoken flag, call taskYield.

Is it OK for me to call vNotifyGiveFromISR from a task instead of from an ISR? The documentation for vNotifyGiveFromISR and vTaskNotifyGiveIndexedFromISR says “Versions of xTaskNotifyGive() and xTaskNotifyGiveIndexed() that can be used from an interrupt service routine (ISR)” but doesn’t mention whether they are safe to call when not in an ISR.

PS - interrupts need to be disabled within the loop anyway, for other reasons.

In my understanding it is port dependent whether it will work or not.

In any case, I would never do that for hygienic reasons; for me the -fromISR postfix always provokes an alert to check whether it is used in an ISR context or not. You may want to create a wrapper that checks the processor state (isr or thread mode) if supported and then dispatches to either with or without -fromISR, that makes it obvious what happens.

Just disable the scheduler with vTaskSuspendAll, and when you are done vTaskResumeAll.

With the scheduler suspended, the tasks you are waking up won’t actually start until you resume the scheduler.

Disabling interrupts might or might not disable the scheduler, depending on the port.

+1. Seems like @dc42 needs to disable interrupts for other reasons though.

That should work if taskENTER_CRITICAL/taskEXIT_CRITICAL macros are used, right?

Which hardware are you using?

I am using ARM Cortex M0+, M4 and M7.

On reflection, for my current use cases it should be sufficient to disable task scheduling rather than disabling interrupts, because currently there are no situations in which an interrupt alters the list of tasks waiting to be notified. Accordingly I shall mark Richards answer as the solution.

As I remember, some ports allows task switching out of a critical section (which re-enables the interrupts, which then get disabled again when the task resumes). I believe these are some ports that don’t use an interrupt to call the scheduler.

The Cortex-M ports all use an interrupt, so the critical section would work, but then you are putting port-specific knowledge into your application.

Ah, right. Such categories of port use an instruction to yield which switches to the handler immediately. Thank you for pointing :slight_smile: