Skip to content

Commit 5ff4250

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 91c20f5 commit 5ff4250

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
@@ -3087,8 +3087,8 @@ void vTaskPlaceOnEventList( List_t * const pxEventList,
30873087
{
30883088
configASSERT( pxEventList );
30893089

3090-
/* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE
3091-
* SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */
3090+
/* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED AND THE QUEUE
3091+
* BEING ACCESSED LOCKED. */
30923092

30933093
/* Place the event list item of the TCB in the appropriate event list.
30943094
* This is placed in the list in priority order so the highest priority task
@@ -4693,22 +4693,25 @@ TickType_t uxTaskResetEventItemValue( void )
46934693
configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES );
46944694

46954695
taskENTER_CRITICAL();
4696+
4697+
/* Only block if the notification count is not already non-zero. */
4698+
if( pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] == 0UL )
46964699
{
4697-
/* Only block if the notification count is not already non-zero. */
4698-
if( pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] == 0UL )
4700+
/* Mark this task as waiting for a notification. */
4701+
pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION;
4702+
4703+
if( xTicksToWait > ( TickType_t ) 0 )
46994704
{
4700-
/* Mark this task as waiting for a notification. */
4701-
pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION;
4705+
traceTASK_NOTIFY_TAKE_BLOCK( uxIndexToWait );
47024706

4703-
if( xTicksToWait > ( TickType_t ) 0 )
4704-
{
4705-
prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
4706-
traceTASK_NOTIFY_TAKE_BLOCK( uxIndexToWait );
4707+
/* Suspend the scheduler before enabling interrupts. */
4708+
vTaskSuspendAll();
4709+
taskEXIT_CRITICAL();
4710+
4711+
prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
47074712

4708-
/* All ports are written to allow a yield in a critical
4709-
* section (some will yield immediately, others wait until the
4710-
* critical section exits) - but it is not something that
4711-
* application code should ever do. */
4713+
if( xTaskResumeAll() == pdFALSE )
4714+
{
47124715
portYIELD_WITHIN_API();
47134716
}
47144717
else
@@ -4718,10 +4721,13 @@ TickType_t uxTaskResetEventItemValue( void )
47184721
}
47194722
else
47204723
{
4721-
mtCOVERAGE_TEST_MARKER();
4724+
taskEXIT_CRITICAL();
47224725
}
47234726
}
4724-
taskEXIT_CRITICAL();
4727+
else
4728+
{
4729+
taskEXIT_CRITICAL();
4730+
}
47254731

47264732
taskENTER_CRITICAL();
47274733
{
@@ -4767,27 +4773,30 @@ TickType_t uxTaskResetEventItemValue( void )
47674773
configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES );
47684774

47694775
taskENTER_CRITICAL();
4776+
4777+
/* Only block if a notification is not already pending. */
4778+
if( pxCurrentTCB->ucNotifyState[ uxIndexToWait ] != taskNOTIFICATION_RECEIVED )
47704779
{
4771-
/* Only block if a notification is not already pending. */
4772-
if( pxCurrentTCB->ucNotifyState[ uxIndexToWait ] != taskNOTIFICATION_RECEIVED )
4780+
/* Clear bits in the task's notification value as bits may get
4781+
* set by the notifying task or interrupt. This can be used to
4782+
* clear the value to zero. */
4783+
pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] &= ~ulBitsToClearOnEntry;
4784+
4785+
/* Mark this task as waiting for a notification. */
4786+
pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION;
4787+
4788+
if( xTicksToWait > ( TickType_t ) 0 )
47734789
{
4774-
/* Clear bits in the task's notification value as bits may get
4775-
* set by the notifying task or interrupt. This can be used to
4776-
* clear the value to zero. */
4777-
pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] &= ~ulBitsToClearOnEntry;
4790+
traceTASK_NOTIFY_WAIT_BLOCK( uxIndexToWait );
47784791

4779-
/* Mark this task as waiting for a notification. */
4780-
pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION;
4792+
/* Suspend the scheduler before enabling interrupts. */
4793+
vTaskSuspendAll();
4794+
taskEXIT_CRITICAL();
47814795

4782-
if( xTicksToWait > ( TickType_t ) 0 )
4783-
{
4784-
prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
4785-
traceTASK_NOTIFY_WAIT_BLOCK( uxIndexToWait );
4796+
prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
47864797

4787-
/* All ports are written to allow a yield in a critical
4788-
* section (some will yield immediately, others wait until the
4789-
* critical section exits) - but it is not something that
4790-
* application code should ever do. */
4798+
if( xTaskResumeAll() == pdFALSE )
4799+
{
47914800
portYIELD_WITHIN_API();
47924801
}
47934802
else
@@ -4797,10 +4806,13 @@ TickType_t uxTaskResetEventItemValue( void )
47974806
}
47984807
else
47994808
{
4800-
mtCOVERAGE_TEST_MARKER();
4809+
taskEXIT_CRITICAL();
48014810
}
48024811
}
4803-
taskEXIT_CRITICAL();
4812+
else
4813+
{
4814+
taskEXIT_CRITICAL();
4815+
}
48044816

48054817
taskENTER_CRITICAL();
48064818
{

0 commit comments

Comments
 (0)