Suggestion: vTaskDelayUntil() should tell whether it is late or not, by return of kernel value xShouldDelay

In a realtime system, It is often essential to know if vTaskDelayUntil() was able to meet the requested deadline or not. It may happen that other tasks takes processor resources such that the caller of vTaskDelayUntil() does not wake at the requested time - it becomes late.

In this thread: https://forums.freertos.org/t/vtaskdelayuntil-how-to-detect-overload/2820 is suggested a method to detect such an event. It says:

“One way to check this is to see if xTaskGetTickCount - lastTickCount (the first parm to
vTaskDelayUntil) is >= tick count given to vTaskDelayUntil…”

However, in the code for vTaskDelayUntil() (filename: tasks.c) this condition is already recorded in the form of the variable xShouldDelay. It looks something like this:

        if (xShouldDelay != pdFALSE) {
		traceTASK_DELAY_UNTIL(xTimeToWake);

		/* prvAddCurrentTaskToDelayedList() needs the block time, not
		the time to wake, so subtract the current tick count. */
		prvAddCurrentTaskToDelayedList(xTimeToWake - xConstTickCount, pdFALSE);
	} else {
		mtCOVERAGE_TEST_MARKER();
	}

vTaskDelayUntil() returns (void) nothing for the moment.

I suggest to…
change vTaskDelayUntil() to return the value (BaseType_t) of xShouldDelay.

I claim that…

  1. It will not break existing code.
  2. This feature is essential - to be able to detect timing issues.
  3. The suggested alternative method is not bullet proof: If the thread gets pre-empted for a long time just after the call to vTaskDelayUntil() but before the verifying call to xTaskGetTickCount() the tick counter may have taken almost a complete cycle (modulus counting) masking the lateness of the wakeup.
  4. The suggested method need to create a copy of the lastTickCount variable passed to vTaskDelayUntil() because vTaskDelayUntil() updates this parameter passed as reference.
  5. The solution to the problem is already solved in the kernel so no need to let the user do it also.

I will add that sometimes I have wished the vTaskDelay() / vTaskDelayUntil() returned an indicator that the delay had been aborted by vTaskAbortDelay(), but there could easily be setup 3 return values for vTaskDelayUntil, and two for vTaskDelay().

Now, changing the return type would mean the name of the function should be changed too, as the leading v is a ‘wart’ to indicate that the function return void, but it would be simple enough to make them xTaskDelay() / xTaskDelayUntil() and have a macro for the v versions that links over to them,

For clarity - is the case you want to detect when vTaskDelayUntil() is called too late to meet its next deadline, so will just return immediately. If so then xShouldDelay is probably what you need. The alternative being that vTaskDelayUntil() was called in time but does not get execution time once it is unblocked so returns late.

Ah yes - good point Barry!.

For clarity - is the case you want to detect when vTaskDelayUntil() is called too late to meet its next deadline, so will just return immediately. If so then xShouldDelay is probably what you need. The alternative being that vTaskDelayUntil() was called in time but does not get execution time once it is unblocked so returns late.

It was the latter case I had in mind - vTaskDelayUntil() is delayed in returning to caller . But both are important.

Again, just discussing to make sure I understand the ask:

In which case I’m not sure how xShouldDelay helps, as that is something set on entry rather than exit. In regards to when the function exits, I don’t think there is any difference between the behaviour of this function than any other that blocks. The scheduler will always unblock a task at the right time, no matter what that task is blocked on (vTaskDelay(), vTaskDelayUntil(), or an object such as a queue, semaphore, stream buffer, etc.) - but in all cases just being unblocked does not mean the task runs as in all cases the task will only run when it is the highest priority task able to run. So in the case of, for example, blocking on a queue with a timeout of 250ms the task will get unblocked after 250ms but will only execute when it is the highest priority task so might not necessarily return from the queue receive function until some time later.

I would presume the first case, calling delay after the target time. Returning too late would in part be not that useful, because delays in getting to the timed code can occur in MANY places, most not detectable by the vTaskDelayUntil call.

The first case detects that you aren’t meeting the requested repletion rate (or at least have temporarily fallen behind). The second is just jitter, until the delay is so big that you miss the next one, which will be caught on the next call to vTaskDelayUntil().

Richard - you are both right, I got is wrong in my head.
xShouldDelay is setup at entry so is not useful to detect late return to the caller!

But xShouldDelay should be useful to detect that the code is falling behind the requested schedule and will not be able to meet the timing no matter how fast the code runs - exactly as you mentioned in your first reply.