|CS 321 Spring 2013 > Lecture Notes for Monday, February 11, 2013|
Hardware support for mutual exclusion involves special processor instructions that perform atomic operations. One simple instruction is Test & Set Lock (TSL. This instruction would be given an register and a memory location (the location of a lock variable). It reads the contents of the memory location into the register and stores a non-zero value into the memory location. All this is done in an atomic manner.
If we have a TSL available, then we can make our
original incorrect locking code
leave_region function is unchanged.
enter_region function can
test the lock by executing TSL.
If we get a non-zero value, then some other thread
has the lock, and we continue looping.
If we get a zero value, then the lock was available,
and we have acquired it.
The x86 architecture does not have a TSL instruction, but it does have something similar: XCHG, which does an atomic exchange of the values of a register and a memory location. Moving a value of 1 into the register beforehard results in the same effect that a TSL would have.
The Priority-Inversion Problem happens when we have a high-priority process/thread busy-waiting on a lower-priority process/thread. We need to give time to the lower-priority process so that it can finish and the higher-priority one can do its work. But standard scheduling algorithms will give more time to the higher-priority process. This is another reason to avoid busy waiting.
The Producer-Consumer Problem occurs when data is being transfered from a “producer” process to a “consumer” process. To avoid busy-waiting, we might have the consumer process check if there is data available, and if not, sleep. Now suppose there is an interrupt between a check (which says there is no data) and the sleep. Then the producer can send data, and wake the consumer ... which is already awake and preparing to sleep. So the producer sends data, and the consumer responds by sleeping. This is another situation when atomic operations are needed.
We discussed semaphores, and in particular binary semaphores, and mutexes. All of these are provided by the kernel, and must perform atomic operations.
We looked at mutexes as implemented in pThreads.
Encapsulating mutual exclusion is a helpful idea. For example, we could write a class whose constructor acquires a lock and whose destructor releases it. An object of this kind with a particular interface is called a monitor.