portBASE_TYPE & critical section

I was comparing the latest FreeROTS version (6.0.2) and an earlier one (version 4.4.0). Here’s what puzzles me: In file tasks.c, function vTaskSuspendAll(), the statement “++uxSchedulerSuspended;” was protected by a critical section in version 4.4.0. While in 6.0.2, it is not, and the comment in 6.0.2 gave the rationale: “A critical section is not required as the variable is of type portBASE_TYPE.” I’m confused – even if the variable is a base type, the “++” essentially is still a load-increment-store. If the current process got interrupted right between “load” and “increment”, and preempted by another process which also calls this same function, the race condition is still there and would cause an error. Am I missing something here? Thanks in advance.

portBASE_TYPE & critical section

The key is when the variable gets written.  If it’s written in one operation then all is well. Consider the following scenario: Task 1 calls vTaskSuspendAll and grabs uxSchedulerSuspended and increments it but doesn’t get a chance to store it because an interrupt occurs.  Task 2 gains control and calls the same function which halts the scheduler.  When task 2 finishes, uxSchedulerSuspended gets decremented back to its original value.  Task 1 regains control and stores the incremented value to suspend the scheduler.  When Task 1 finishes, uxSchedulerSuspended gets decremented and the scheduler starts again. If it took two writes to store uxSchedulerSuspended, then there would be a danger since the first write would corrupt the value until the second write was done.  An interrupt between the writes would cause any task using that variable to use a corrupted value.

portBASE_TYPE & critical section

Another way to take a look at this, and it is based on the essential nature of the variable, is to look at what happens with different values of the variable. If it is non-zero at the start, then if an interrupt comes between the read and the write, so no problems can occur. If it is zero at the start, then an interrupt might cause a task switch, but if it does, when it get back to this task, the variable will be zero again. The key feature is there is only a single value of this variable that allows a task change, so there is no danger of it change behind the operations back.