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

* Don't suspend scheduler if task already notified
This commit is contained in:
Jeff Tenney 2024-11-12 04:05:33 -07:00 committed by GitHub
parent 9736947af2
commit 8f7f451c2a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

134
tasks.c
View file

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