In this lesson, you will learn how to identify critical sections in your code and understand how uncontrolled concurrent access to shared memory destroys system determinism.
The Nature of Critical Sections
In an RTOS environment, a critical section is a specific block of code that accesses a shared resource—such as a global variable, a peripheral register, or a data structure—that must not be interrupted or accessed by another task simultaneously. If two tasks attempt to modify the same memory location at the same time, you encounter a "race condition," where the final state of the data depends on the unpredictable timing of the scheduler.
Identifying the Risk
Consider a simple task that updates a global counter used to track system events:
// Shared variable
int event_count = 0;
void Task_A(void *pvParameters) {
while(1) {
// Critical Section Start
int temp = event_count;
temp++;
event_count = temp;
// Critical Section End
}
}
In assembly, the increment operation event_count++ is rarely atomic; it usually involves a load, an add, and a store instruction. If the RTOS performs a context switch immediately after Task A performs the load but before the store, a second task (Task B) might modify event_count. When control returns to Task A, it will overwrite Task B’s changes with its own stale data.
Why This Destroys Determinism
When access to shared memory is uncontrolled, the system's behavior becomes non-deterministic. The result of a calculation or the value of a status flag suddenly depends on the precise microsecond the scheduler decided to perform a context switch. In real-time systems, this leads to intermittent, "heisenbug" errors that are notoriously difficult to reproduce because they only occur under specific timing conditions.
To maintain a predictable system, you must define these boundaries clearly. By isolating the code that performs the "read-modify-write" sequence, you ensure that the transaction remains atomic relative to other tasks. Only by protecting these segments can you guarantee that your task state transitions and data integrity remain consistent regardless of scheduler activity.
Key Takeaway: A critical section is any code segment accessing shared resources where atomicity must be preserved to prevent race conditions and non-deterministic system failure.