CS 422 - HOMEWORK 2 SOLUTION Page 1 ---------------------------- Version 2, Oct. 27, 1998 Problem 1 --------- a) The machine code for "tally = tally + 1" is: LOAD R1,TALLY INC R1 STORE R1,TALLY The maximum value of 'tally' will be 100 and the minimum value will be 50. The "+" operation is performed 100 times. If each takes affect and there are 2 processes, tally will get incremented 100 times. This can occur so long as both processes see (LOAD) the value of 'tally' produced by the other process. The minimum value occurs when each process reads the same value of 'tally'. This can occur, for example, if they execute LOAD at the same time. b) For N threads, the maximum value will be 50N, and the minimum value will be 50. Problem 2 --------- Execution with no interchanges involves the following usage of semaphores: o notEmpty: Whenever there is atleast 1 item in the buffer o enter: Protect the critical region o freeslot: Control use of free buffer slots a) Interchange 1: Deadlock if 1) there are no free slots, 2) a Producer enters its critical region, and later 3) a Consumer tries to enter its critical region. b) Interchange 2: OK c) Interchange 3: Deadlock if 1) a Consumer enters its critical region, and 2) it waits because of an empty buffer. The Producer gets stuck waiting for the Consumer to signal that it is out of its critical region. d) Interchange 4: OK Note that deadlock occurs in all cases because a process waits inside its critical region. So, a process should exit its critical region before waiting for a signal. Problem 3 --------- a) A semaphore protects the process wait queue associated with Mywait and Mysignal. Mywait(X): while (test&set(X) == 1) ... do nothing ... ; Place this process in wait queue; X = 0; Suspend; Mysignal(X): while (test&set(X) == 1) ... do nothing ... ; if (non-empty queue) then Wake up process at the head of the queue; X = 0; b) The new primitives aren't very good for implementing the Wait() and Signal() primitives because we need another semaphore to protect a counter. It would be better if these primitives depended on some other primitive for mutual exclusion. Problem 4 --------- a) In 'Signal(...)', the conditional should be: if (S <= 0) Bsignal(Y); b) X: mutual exclusion Y: signal waiting process in Wait() Problem 5 --------- a) Atomic read/write of memory b) The movie looks like: Process 0 Process 1 --------- --------- choosing[0] = TRUE choosing[1] = TRUE number[0] = 1 number[1] = 1 choosing[0] = FALSE choosing[1] = FALSE (number[0] != 0) and (number[0] != 0) and (number[0],0) < (number[0],0) (number[0],0) < (number[1],1) do; number[0] = 0 (number[0] != 0) and (number[0],0) < (number[1],1) do; number[1] = 0 Process 1 stutters when it reaches the second while and in effect, doesn't continue forward until process 0 sets number[0] to 0.. Problem 6 --------- *** The original problem had a typgraphical error in the matrix Q. *** The solution below solves the updated problem in which row 3 of Q is *** (2 1 0 0) instead of (2 2 0 0). The original matrix leads to no safe *** path. U = (2 1 0 0) Q = (2 0 0 1) A = (0 0 1 0) (1 0 1 0) (2 0 0 1) (2 1 0 0) (0 1 2 0) Look for a safe execution path (sequence of process executions). step 2) W = (2 1 0 0) step 3) Q_3 <= W; Mark P3 step 4) W = (2 2 2 0) step 3) Q_2 <= W; Mark P2 step 4) W = (4 2 2 1) step 3) Q_1 <= W; Mark P1 There is a safe path. Problem 7 --------- a) The maximum allocation without any process getting its complete request results in the use of 1 research for each of the 3 processes. This leaves 1 resource that can be given to any process to satisfy its maximum demand. When it completes, the next process can meet its demand. This continues to completion. So, no deadlock can occur. b) *** There was something wrong with this problem. It needs to be fixed. *** The answer below is meaningless until it gets fixed. If no process gets its maximum demand, the number of allocated resources will be (M+N-1) - N = M - 1. This leaves 1 free resource which can be used to continue any of the N processes. When it finishes, it returns its resources to the resource pool. This will continue until every process executes to completion. So, no deadlock can occur.