The following program, from (Peterson 1981), is a means, implemented without any special hardware or operating-system support, for two threads to have mutually exclusive access to a region of data or code. Each thread calls peterson with its own ID, which is either 0 or 1. It assumes that each thread is running on a separate processor and that the memory holding the shared variables is strictly coherent, meaning that a store into a memory location by one processor will be seen by the other processor if it does a load from that location immediately thereafter.
The variables loser and active are shared by both threads, the other variables are private to each of the threads (i.e., each has its own copy). The idea is that the active array is a pair of fl ags, one for each thread, that the thread sets to indicate that it has entered the “critical section,” in which the shared variable count is incremented. Each thread, before entering the critical section, sets its entry in active, then checks the other thread’s entry to see if that thread is already in the critical section. If so, the thread waits, by repeatedly checking the array. Of course, it is possible that both threads attempt to enter at the same time. This is where the loser variable comes in: after setting its active entry to 1, a thread sets loser to its own ID. If both threads are attempting to enter the critical section, loser’s value will be the ID of just one of the two threads. That thread must yield to the other. a. Write a program that tests whether this algorithm works. To do so, have two threads call peterson, with iterations set to a large number, such as two billion. If the code correctly provides mutual exclusion, then the fi nal value of count will be twice the value of iterations. If not, it will be less. Explain why. b. Modern shared-memory multiprocessor computers (including computers employing multicore chips) do not have strictly coherent memory. Instead, the effect of stores to memory is delayed a bit: when one processor stores a value into a memory location, loads by other processors might not retrieve the new value until after a few clock cycles (though loads by the processor performing the store will retrieve the new value, since it is in that processor’s memory cache). Explain why peterson does not always work correctly on modern share-memory multiprocessors.