20. July, 2004
20. July, 2004
in by Michael Neumann
In a multi-threaded kernel (or more generally in any multi-threaded application), you sometimes have to prevent two or more threads from reading or writing to the same data structure. Otherwise unexpected results may appear, depending on the order in which the threads run (race conditions). Sections of code that are not allowed to be in execution by more than one thread are called critical sections.

Example (in pseudo Ruby code):

# global data
$AMOUNT = 1000

critical_section {
  amount = $AMOUNT
  amount += 10
  $AMOUNT = amount
}

Imagine that the critical section in the example above could be entered and executed by two threads A and B. First, thread A enters the section and executes the first two lines, but before it can write the result back to the global variable, it gets preempted by thread B. Thread B now reads the current value of $AMOUNT, which is at this time still 1000. Thread B is not interrupted and finishs the section by writing back it’s new calculated result of 1010 to $AMOUNT. Now, thread A comes back to life and proceeds with it’s execution where it was interrupted by thread B (before the last line) and writes it’s result (which is 1010, too) into the $AMOUNT variable.

Clearly, the result is wrong! It should be 1020! And if there would have be no interruption of thread A by thread B, the result would be 1020. These kinds of errors are very hard to find, as in 99.999% of all cases the correct result is calculated.

Critical sections are usually implemented with mutexes. See SyncPrim for more about this topic and synchronization in general.