I am evaluating the use of FreeRTOS in an application. As part of this, I have
been reading the source code. There is a location where I am confused on how
concurrency issues are prevented on the xNextTaskUnblockTime variable.
My concerning case is the following. I know it’s complicated, but I hope it
shows the point.
4 Tasks from highest to lowest priority:
A Highest priority, but blocked waiting on I/O
B Waiting to wake in 100 ticks
C Running
D Sleeping, lowest priority
C calls vTaskSuspend to suspend D (task.c:1191)
START_CRITICAL
pxTCB is task to suspend
removes from ready/delayed list
removes from event list
add to suspended list
END_CRITICAL
call prvResetNextTaskUnblockTime (task.c:1262 calling task.c:3090)
delayed list is not empty
get the owner of head entry
calc the xNextTaskUnblockTime for 100 ticks later, but not yet stored.
The IO interrupt unblocks task A
A runs, does stuff.
A calls vTaskSuspend for itself for 1 ticks.
This updates the xNextTaskUnblockTime for 5 ticks later.
C runs again, finishing the assignment of setting xNextTaskUnblockTime for 100 ticks later.
I think this is an error.
…time passes…
xTaskIncrementTick is called. (task.c:1841)
NOTE: uxScheduler suspended is false.
++xTickCount
NOTE: No switch is required.
xConstTickCount is NOT greater/equal than the tick count (even though it should be.)
On first inspection I agree, this does look like an error, and if it turns out to be so the same error is probably in the vTaskDelete() function. Again, only from a first preliminary inspection, the other uses of xNextTaskUnblockTime look ok.
This will get investigated fully. Expect to be able to report back within 10 days (hopefully sooner). In the mean time putting a critical section around the call to prvResetNextTaskUnblockTime() will not do any harm, but definitely do not put the critical section inside the call to prvResetNextTaskUnblockTime() as that definitely will do some harm (on some ports anyway).