Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't suspend scheduler if task already notified #1190

Merged
merged 3 commits into from
Nov 12, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 70 additions & 69 deletions tasks.c
Original file line number Diff line number Diff line change
Expand Up @@ -7653,68 +7653,68 @@ TickType_t uxTaskResetEventItemValue( void )
TickType_t xTicksToWait )
{
uint32_t ulReturn;
BaseType_t xAlreadyYielded, xShouldBlock = pdFALSE;

traceENTER_ulTaskGenericNotifyTake( uxIndexToWaitOn, xClearCountOnExit, xTicksToWait );

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();
BaseType_t xAlreadyYielded, xShouldBlock = pdFALSE;
jefftenney marked this conversation as resolved.
Show resolved Hide resolved

/* 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
{
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();
{
Expand Down Expand Up @@ -7757,72 +7757,73 @@ TickType_t uxTaskResetEventItemValue( void )
uint32_t * pulNotificationValue,
TickType_t xTicksToWait )
{
BaseType_t xReturn, xAlreadyYielded, xShouldBlock = pdFALSE;
BaseType_t xReturn;

traceENTER_xTaskGenericNotifyWait( uxIndexToWaitOn, ulBitsToClearOnEntry, ulBitsToClearOnExit, pulNotificationValue, xTicksToWait );

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();
BaseType_t xAlreadyYielded, xShouldBlock = pdFALSE;

/* 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;
/* 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;
/* Mark this task as waiting for a notification. */
pxCurrentTCB->ucNotifyState[ uxIndexToWaitOn ] = taskWAITING_NOTIFICATION;

if( xTicksToWait > ( TickType_t ) 0 )
{
/* Arrange to wait for a notification. */
xShouldBlock = pdTRUE;
}
else
{
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();
{
Expand Down
Loading