The answers to assignment number 1 : ------------------------------------ *********** ** 2.3 ** *********** With busy waiting, a process keeps testing for some condition. It is constantly using the CPU, sitting in a tight loop. With blocking, a process gives up the CPU and is awakened later when the condition it is waiting for has become true. A blocked process does not use the CPU. *********** ** 2.6 ** *********** TSL is a low-level operation used by kernel to implement semaphores or other high-level blocking primitives. TSL is a busy waiting lock that is normally used for waiting for a very short period of time to enter a short critical section. It is not suitable for long-term waiting. Semaphores use interrupt disabling during DOWN and UP operations. In the case of multiple CPU's, this does not prevent other CPU's from accessing the semaphore. The solution is to use TSL's which block the memory bus during access to the semaphores. Hence, TSL and semaphores don't compete; they serve different purposes. NOTE : Semaphores and monitors compete; one can be replaced by the other. but: Semaphores and monitors don't conflict : they can be used together. Don't confuse the two. Question asked why TSL and semaphores don't *compete* with each other. *********** ** 2.7 ** *********** Book describes one fatal race condition when count is 0 and the line : if (count == 0) sleep(); is interrupted just before the consumer sleeps, and line : if (count == 1) wakeup(consumer); is executed by the producer before execution gets back to consumer, resulting in the loss of the wakeup call. The symmetrical fatal race condition also comes to mind. Count = N and line : if (count == N) sleep(); is interrupted just before the producer sleeps, and line : if (count == N-1) wakeup(producer); is executed, resulting in the loss of the wakeup call. This was not asked in the question. Actually, both of these race conditions were mentioned in the question as : " ... if either process decides to go to sleep and is descheduled ^^^^^^ just before it calls sleep, a wakeup can be lost." Another race condition, that depends on the variable count is when either of the lines : count = count + 1; count = count - 1; is interrupted. Let's assume that the count is m. The producer enters an item in the buffer and reads the count to increment it. But it is descheduled before m+1 is written back to count. Now, the consumer consumes one item (item m+1) and decrements count from m to m-1. When the execution gets back to the producer, the change made to count by consumer will be ignored, and count will become m+1, although there are m items in the buffer. In time, the consumer will try to consume an item that doesn't exist! If c is a local variable that holds the value of count for producer : Producer # of items count Consumer m m enter_item(.); m+1 m c = count; m+1 m ... m m remove_item(.); m m-1 count = count - 1; ... count = c + 1; m m+1 ----------------------------------- I have split the non-atomic instruction count = count + 1 in its two atomic subinstructions.