Skip to content

[BUG] xTaskDelayUntil updates pxPreviousWakeTime incorrectly in case of deadline miss #1339

@INOMO-RKr

Description

@INOMO-RKr

Describe the bug
If the targeted wake-up time is already in the past, i.e. xTaskDelayUntil( &previousWakeUpTime, xTimeIncrement ) == pdFALSE then previousWakeUpTime is incremented by the specied delay ticks, and goes out of sync with the actual ticks.

Target

  • All

To Reproduce
Call the function in a way that the specified deadline is missed.

Expected behavior
After a call to xTaskDelayUnitl(&previousWakeUpTime, xTimeIncrement ) the variable previousWakeUpTime holds the current ticks.
according to the functions documentation:

/**
 * @param pxPreviousWakeTime Pointer to a variable that holds the time at which the
 * task was last unblocked.  The variable must be initialised with the current time
 * prior to its first use (see the example below).  Following this the variable is
 * automatically updated within xTaskDelayUntil ().
*/

OR
The documentation clearly describes the current behavior.

Additional context
Relevant section in source code

FreeRTOS-Kernel/tasks.c

Lines 1231 to 1265 in 151fb04

xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;
if( xConstTickCount < *pxPreviousWakeTime )
{
/* The tick count has overflowed since this function was
* lasted called. In this case the only time we should ever
* actually delay is if the wake time has also overflowed,
* and the wake time is greater than the tick time. When this
* is the case it is as if neither time had overflowed. */
if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) )
{
xShouldDelay = pdTRUE;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
/* The tick time has not overflowed. In this case we will
* delay if either the wake time has overflowed, and/or the
* tick time is less than the wake time. */
if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) )
{
xShouldDelay = pdTRUE;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
/* Update the wake time ready for the next call. */
*pxPreviousWakeTime = xTimeToWake;

            /* Generate the tick time at which the task wants to wake. */
            xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;
/*...
Lines omitted for clarity 
...*/
            *pxPreviousWakeTime = xTimeToWake; 

it is clear that the update of *pxPreviousWakeTime is the same irregardless of if the deadline is missed or not.

Example
This causes in the following example the previousWakeTime and xTaskGetTickCount() to diverge.

void exampleTaskFunction(void)
{
    TickType_t previousWakeUpTime = xTaskGetTicks();
    const TickType_t cDelayTicks = 5;
    while(true)
    {
        vTaskDelay(10*cDelayTicks) /*Simple way to force a deadline miss*/
       if(!xTaskDelayUntil(&previousWakeUpTime, cDelayTicks) )
      { /*Always true*/
        assert(xTaskGetTicks() != previousWakeUpTime);
      }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions