September 05, 2007
Use Critical Sections (Preferably Locks) to Eliminate RacesCode Must Never Move Out
Let's see what "code can't move out" means in the context of the following code, which acquires a mutex mut that protects two integers x and y:
What are the legal reorderings of the assignment to x? It is perfectly legal for the system to transform the above code to:
because both assignments still happen inside the protected critical section (and do not otherwise depend on each other, assuming x and y are independent and not aliased). A system may not, however, transform the code to either
or
because either of these would move the assignment outside the critical section and therefore create a potential race on x.
So what about moving code into a critical section?
It's Okay For Code to Move In
Consider an adapted example:
What are the legal reorderings of the assignments to x and z? Again assuming that x, y, and z are independent and not aliased, it is perfectly legal for the system to transform the above code to:
Even though the moved lines now run while holding the lock, it doesn't alter the meaning or correctness of the code. It is always safe to add extra guarantees; in this case, to hold a lock a little longer.
But it is not safe to arbitrarily remove guarantees, such as to fail to hold a needed lock. Therefore, a system cannot arbitrarily reorder the code to cross either fence the wrong way:
Note that this is true even though the assignments to x and z were not initially inside the critical section. For example, what if setting y = "universe" is treated as a flag that tells another thread that x is now ready to be shared, so that y publishes x? That is why no code must pass the release fence in the downward direction. [3]
|
|
||||||||||||||||||||||||||||||
|
|
|
|