1a) Just about anything that is deadlock is acceptable here - I was pretty lenient in terms of what I accepted. The best examples of deadlock are those where there are two or more parties, each of which requires two or more shared resources. However, none of the parties can proceed, since each has exactly one of the contested resources, and none of the parties are willing to give up its resource until it's done doing whatever it wants to do. As an example, let's say two roommates share a computer. Both have a term paper to write that is due tomorrow morning, so they both need the computer. One of the roommates thinks ahead, and hides the monitor in a safe place, so he will have access to it, but his roommate will not. Similarly, the other roommate hides the keyboard in a safe place so the first can't have it. Of course, neither can admit to the other that they hid their component, since that would irrepairably damage their friendship. Since both roommates need both the monitor and keyboard to write their paper, they are in deadlock. 1b) Again, I was lenient in terms of what I allowed as starvation. Here, an example would be a limo driver circling a block, looking for a parking spot. On each time around, some cars pull out, and some other cars pull in, but there is never a parking spot large enough for his limo when he is driving past. 2a) We just wanted an interleave of statements that would show A sucessfully entering the critical section, and B being blocked as long as A is in the critical section. A1 A2 A3 B1 B2 B1 B2 A4 B1 B2 B3 B4 Where the number represents the statement to be executed (ie, 1,2,3 are the respective lines of code in the entry code, and 4 is the line of the exit code). 2b) We wanted an interleave of statements where A and B get into the critical section at the same time: A1 B1 A2 B2 A3 B3 A4 B4 The idea behind this is that the code given in this problem is a BAD way to implement a semaphore. This is because a semaphore must be atomic (ie, checking if it can enter, and then entering the critical section in one CPU cycle). If it is not atomic, like in this problem, then it is possible for two processes to enter their critical sections at the same time. 3) semaphore s1=0, s2=0, s3=0, s4=0; cobegin p1; V(s1); V(s1); V(s1); // P(s1); p2; V(s2); V(s2); // P(s2); p3; V(s4); // P(s2); p4; V(s3); // P(s1); p5; V(s3); // P(s3); P(s3); p6; V(s4); // P(s1); p7; V(s4); // P(s4); P(s4); P(s4); p8; coend The syntax isn't the important part of the problem. You had to: (1) Identify the semaphores you were using and their initial values. and (2) For each process, indicates the P and V operations for synchronization. There were a number of solutions accepted for this also: One popular varient was to initialize s3 to -1 and s4 to -2, and remove one of the "P(s3)"s from p6's line, and two of the "P(s4)"s from p8's line. 4a) Interchanging P(e) and P(b) could cause deadlock. To illustrate this, assume that the buffer is ful land te producer continues at this time. It performs P(b), which succeeds, followed by P(e), which blocks the proces. Since b=0, the consumer will not be ale to proceed to produce a new record. Hence both processes are stuck forever. 4b) Interchanging the V operations has no adverse effect.