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
D Sleeping, lowest priority
C calls vTaskSuspend to suspend D (task.c:1191)
pxTCB is task to suspend
removes from ready/delayed list
removes from event list
add to suspended list
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.
xTaskIncrementTick is called. (task.c:1841)
NOTE: uxScheduler suspended is false.
NOTE: No switch is required.
xConstTickCount is NOT greater/equal than the tick count (even though it should be.)
Is there something I'm missing.
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).
Thanks for your input.
See lines 765 and 1268 on the following link (or at least revision 2233 of the file). Please let me know if you see any issues.
I read through it again, and I don't see any other issues on that variable.
All reads are atomic, and
It looks like the variable is written only when:
1. In non-interrupts where the scheduler is suspended, or
2. In non-interrupts where interrupts are disabled, or
3. In interrupts where it has determined that the scheduler is suspended.