Don't suspend scheduler if task already notified (#1190)

* Don't suspend scheduler if task already notified
diff --git a/tasks.c b/tasks.c
index 421dea7..22e11f0 100644
--- a/tasks.c
+++ b/tasks.c
@@ -7659,24 +7659,27 @@
 
         configASSERT( uxIndexToWaitOn < configTASK_NOTIFICATION_ARRAY_ENTRIES );
 
-        /* We suspend the scheduler here as prvAddCurrentTaskToDelayedList is a
-         * non-deterministic operation. */
-        vTaskSuspendAll();
+        /* If the notification count is zero, and if we are willing to wait for a
+         * notification, then block the task and wait. */
+        if( ( pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ] == 0U ) && ( xTicksToWait > ( TickType_t ) 0 ) )
         {
-            /* We MUST enter a critical section to atomically check if a notification
-             * has occurred and set the flag to indicate that we are waiting for
-             * a notification. If we do not do so, a notification sent from an ISR
-             * will get lost. */
-            taskENTER_CRITICAL();
+            /* We suspend the scheduler here as prvAddCurrentTaskToDelayedList is a
+             * non-deterministic operation. */
+            vTaskSuspendAll();
             {
-                /* Only block if the notification count is not already non-zero. */
-                if( pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ] == 0U )
+                /* We MUST enter a critical section to atomically check if a notification
+                 * has occurred and set the flag to indicate that we are waiting for
+                 * a notification. If we do not do so, a notification sent from an ISR
+                 * will get lost. */
+                taskENTER_CRITICAL();
                 {
-                    /* Mark this task as waiting for a notification. */
-                    pxCurrentTCB->ucNotifyState[ uxIndexToWaitOn ] = taskWAITING_NOTIFICATION;
-
-                    if( xTicksToWait > ( TickType_t ) 0 )
+                    /* Only block if the notification count is not already non-zero. */
+                    if( pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ] == 0U )
                     {
+                        /* Mark this task as waiting for a notification. */
+                        pxCurrentTCB->ucNotifyState[ uxIndexToWaitOn ] = taskWAITING_NOTIFICATION;
+
+                        /* Arrange to wait for a notification. */
                         xShouldBlock = pdTRUE;
                     }
                     else
@@ -7684,37 +7687,33 @@
                         mtCOVERAGE_TEST_MARKER();
                     }
                 }
+                taskEXIT_CRITICAL();
+
+                /* We are now out of the critical section but the scheduler is still
+                 * suspended, so we are safe to do non-deterministic operations such
+                 * as prvAddCurrentTaskToDelayedList. */
+                if( xShouldBlock == pdTRUE )
+                {
+                    traceTASK_NOTIFY_TAKE_BLOCK( uxIndexToWaitOn );
+                    prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
+                }
                 else
                 {
                     mtCOVERAGE_TEST_MARKER();
                 }
             }
-            taskEXIT_CRITICAL();
+            xAlreadyYielded = xTaskResumeAll();
 
-            /* We are now out of the critical section but the scheduler is still
-             * suspended, so we are safe to do non-deterministic operations such
-             * as prvAddCurrentTaskToDelayedList. */
-            if( xShouldBlock == pdTRUE )
+            /* Force a reschedule if xTaskResumeAll has not already done so. */
+            if( ( xShouldBlock == pdTRUE ) && ( xAlreadyYielded == pdFALSE ) )
             {
-                traceTASK_NOTIFY_TAKE_BLOCK( uxIndexToWaitOn );
-                prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
+                taskYIELD_WITHIN_API();
             }
             else
             {
                 mtCOVERAGE_TEST_MARKER();
             }
         }
-        xAlreadyYielded = xTaskResumeAll();
-
-        /* Force a reschedule if xTaskResumeAll has not already done so. */
-        if( ( xShouldBlock == pdTRUE ) && ( xAlreadyYielded == pdFALSE ) )
-        {
-            taskYIELD_WITHIN_API();
-        }
-        else
-        {
-            mtCOVERAGE_TEST_MARKER();
-        }
 
         taskENTER_CRITICAL();
         {
@@ -7763,28 +7762,31 @@
 
         configASSERT( uxIndexToWaitOn < configTASK_NOTIFICATION_ARRAY_ENTRIES );
 
-        /* We suspend the scheduler here as prvAddCurrentTaskToDelayedList is a
-         * non-deterministic operation. */
-        vTaskSuspendAll();
+        /* If the task hasn't received a notification, and if we are willing to wait
+         * for it, then block the task and wait. */
+        if( ( pxCurrentTCB->ucNotifyState[ uxIndexToWaitOn ] != taskNOTIFICATION_RECEIVED ) && ( xTicksToWait > ( TickType_t ) 0 ) )
         {
-            /* We MUST enter a critical section to atomically check and update the
-             * task notification value. If we do not do so, a notification from
-             * an ISR will get lost. */
-            taskENTER_CRITICAL();
+            /* We suspend the scheduler here as prvAddCurrentTaskToDelayedList is a
+             * non-deterministic operation. */
+            vTaskSuspendAll();
             {
-                /* Only block if a notification is not already pending. */
-                if( pxCurrentTCB->ucNotifyState[ uxIndexToWaitOn ] != taskNOTIFICATION_RECEIVED )
+                /* We MUST enter a critical section to atomically check and update the
+                 * task notification value. If we do not do so, a notification from
+                 * an ISR will get lost. */
+                taskENTER_CRITICAL();
                 {
-                    /* Clear bits in the task's notification value as bits may get
-                     * set by the notifying task or interrupt. This can be used
-                     * to clear the value to zero. */
-                    pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ] &= ~ulBitsToClearOnEntry;
-
-                    /* Mark this task as waiting for a notification. */
-                    pxCurrentTCB->ucNotifyState[ uxIndexToWaitOn ] = taskWAITING_NOTIFICATION;
-
-                    if( xTicksToWait > ( TickType_t ) 0 )
+                    /* Only block if a notification is not already pending. */
+                    if( pxCurrentTCB->ucNotifyState[ uxIndexToWaitOn ] != taskNOTIFICATION_RECEIVED )
                     {
+                        /* Clear bits in the task's notification value as bits may get
+                         * set by the notifying task or interrupt. This can be used
+                         * to clear the value to zero. */
+                        pxCurrentTCB->ulNotifiedValue[ uxIndexToWaitOn ] &= ~ulBitsToClearOnEntry;
+
+                        /* Mark this task as waiting for a notification. */
+                        pxCurrentTCB->ucNotifyState[ uxIndexToWaitOn ] = taskWAITING_NOTIFICATION;
+
+                        /* Arrange to wait for a notification. */
                         xShouldBlock = pdTRUE;
                     }
                     else
@@ -7792,37 +7794,33 @@
                         mtCOVERAGE_TEST_MARKER();
                     }
                 }
+                taskEXIT_CRITICAL();
+
+                /* We are now out of the critical section but the scheduler is still
+                 * suspended, so we are safe to do non-deterministic operations such
+                 * as prvAddCurrentTaskToDelayedList. */
+                if( xShouldBlock == pdTRUE )
+                {
+                    traceTASK_NOTIFY_WAIT_BLOCK( uxIndexToWaitOn );
+                    prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
+                }
                 else
                 {
                     mtCOVERAGE_TEST_MARKER();
                 }
             }
-            taskEXIT_CRITICAL();
+            xAlreadyYielded = xTaskResumeAll();
 
-            /* We are now out of the critical section but the scheduler is still
-             * suspended, so we are safe to do non-deterministic operations such
-             * as prvAddCurrentTaskToDelayedList. */
-            if( xShouldBlock == pdTRUE )
+            /* Force a reschedule if xTaskResumeAll has not already done so. */
+            if( ( xShouldBlock == pdTRUE ) && ( xAlreadyYielded == pdFALSE ) )
             {
-                traceTASK_NOTIFY_WAIT_BLOCK( uxIndexToWaitOn );
-                prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
+                taskYIELD_WITHIN_API();
             }
             else
             {
                 mtCOVERAGE_TEST_MARKER();
             }
         }
-        xAlreadyYielded = xTaskResumeAll();
-
-        /* Force a reschedule if xTaskResumeAll has not already done so. */
-        if( ( xShouldBlock == pdTRUE ) && ( xAlreadyYielded == pdFALSE ) )
-        {
-            taskYIELD_WITHIN_API();
-        }
-        else
-        {
-            mtCOVERAGE_TEST_MARKER();
-        }
 
         taskENTER_CRITICAL();
         {