Skip to content

Commit 8daadaf

Browse files
committed
Fix task notification determinism.
- Delayed task list is no longer walked while interrupts are disabled. - Fixed comment that could lead to similar mistakes in the future. - Minimize performance impact.
1 parent 1b8a424 commit 8daadaf

File tree

1 file changed

+46
-34
lines changed

1 file changed

+46
-34
lines changed

tasks.c

+46-34
Original file line numberDiff line numberDiff line change
@@ -3137,8 +3137,8 @@ void vTaskPlaceOnEventList( List_t * const pxEventList,
31373137
{
31383138
configASSERT( pxEventList );
31393139

3140-
/* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE
3141-
* SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */
3140+
/* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED AND THE QUEUE
3141+
* BEING ACCESSED LOCKED. */
31423142

31433143
/* Place the event list item of the TCB in the appropriate event list.
31443144
* This is placed in the list in priority order so the highest priority task
@@ -4744,22 +4744,25 @@ TickType_t uxTaskResetEventItemValue( void )
47444744
configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES );
47454745

47464746
taskENTER_CRITICAL();
4747+
4748+
/* Only block if the notification count is not already non-zero. */
4749+
if( pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] == 0UL )
47474750
{
4748-
/* Only block if the notification count is not already non-zero. */
4749-
if( pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] == 0UL )
4751+
/* Mark this task as waiting for a notification. */
4752+
pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION;
4753+
4754+
if( xTicksToWait > ( TickType_t ) 0 )
47504755
{
4751-
/* Mark this task as waiting for a notification. */
4752-
pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION;
4756+
traceTASK_NOTIFY_TAKE_BLOCK( uxIndexToWait );
47534757

4754-
if( xTicksToWait > ( TickType_t ) 0 )
4755-
{
4756-
prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
4757-
traceTASK_NOTIFY_TAKE_BLOCK( uxIndexToWait );
4758+
/* Suspend the scheduler before enabling interrupts. */
4759+
vTaskSuspendAll();
4760+
taskEXIT_CRITICAL();
4761+
4762+
prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
47584763

4759-
/* All ports are written to allow a yield in a critical
4760-
* section (some will yield immediately, others wait until the
4761-
* critical section exits) - but it is not something that
4762-
* application code should ever do. */
4764+
if( xTaskResumeAll() == pdFALSE )
4765+
{
47634766
portYIELD_WITHIN_API();
47644767
}
47654768
else
@@ -4769,10 +4772,13 @@ TickType_t uxTaskResetEventItemValue( void )
47694772
}
47704773
else
47714774
{
4772-
mtCOVERAGE_TEST_MARKER();
4775+
taskEXIT_CRITICAL();
47734776
}
47744777
}
4775-
taskEXIT_CRITICAL();
4778+
else
4779+
{
4780+
taskEXIT_CRITICAL();
4781+
}
47764782

47774783
taskENTER_CRITICAL();
47784784
{
@@ -4818,27 +4824,30 @@ TickType_t uxTaskResetEventItemValue( void )
48184824
configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES );
48194825

48204826
taskENTER_CRITICAL();
4827+
4828+
/* Only block if a notification is not already pending. */
4829+
if( pxCurrentTCB->ucNotifyState[ uxIndexToWait ] != taskNOTIFICATION_RECEIVED )
48214830
{
4822-
/* Only block if a notification is not already pending. */
4823-
if( pxCurrentTCB->ucNotifyState[ uxIndexToWait ] != taskNOTIFICATION_RECEIVED )
4831+
/* Clear bits in the task's notification value as bits may get
4832+
* set by the notifying task or interrupt. This can be used to
4833+
* clear the value to zero. */
4834+
pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] &= ~ulBitsToClearOnEntry;
4835+
4836+
/* Mark this task as waiting for a notification. */
4837+
pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION;
4838+
4839+
if( xTicksToWait > ( TickType_t ) 0 )
48244840
{
4825-
/* Clear bits in the task's notification value as bits may get
4826-
* set by the notifying task or interrupt. This can be used to
4827-
* clear the value to zero. */
4828-
pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] &= ~ulBitsToClearOnEntry;
4841+
traceTASK_NOTIFY_WAIT_BLOCK( uxIndexToWait );
48294842

4830-
/* Mark this task as waiting for a notification. */
4831-
pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION;
4843+
/* Suspend the scheduler before enabling interrupts. */
4844+
vTaskSuspendAll();
4845+
taskEXIT_CRITICAL();
48324846

4833-
if( xTicksToWait > ( TickType_t ) 0 )
4834-
{
4835-
prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
4836-
traceTASK_NOTIFY_WAIT_BLOCK( uxIndexToWait );
4847+
prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
48374848

4838-
/* All ports are written to allow a yield in a critical
4839-
* section (some will yield immediately, others wait until the
4840-
* critical section exits) - but it is not something that
4841-
* application code should ever do. */
4849+
if( xTaskResumeAll() == pdFALSE )
4850+
{
48424851
portYIELD_WITHIN_API();
48434852
}
48444853
else
@@ -4848,10 +4857,13 @@ TickType_t uxTaskResetEventItemValue( void )
48484857
}
48494858
else
48504859
{
4851-
mtCOVERAGE_TEST_MARKER();
4860+
taskEXIT_CRITICAL();
48524861
}
48534862
}
4854-
taskEXIT_CRITICAL();
4863+
else
4864+
{
4865+
taskEXIT_CRITICAL();
4866+
}
48554867

48564868
taskENTER_CRITICAL();
48574869
{

0 commit comments

Comments
 (0)