Project 4A: The Battling Buffet

Note: Project 4 has been split into two smaller "puzzles", one due before spring break, the other due after. Together, they will have the weight of one "project".

Project Goals

In this project, you will:
  1. learn and apply basic thread synchronization primitives
  2. reason about problems in concurrency and synchronization
  3. study the relationship between deadlock, liveness, and fairness

The Hatfields and the McCoys

The Hatfields and McCoys are two famously feuding families described by Mark Twain. Their modern descendants are shocked to discover that Henrietta Hatfield and Matthew McCoy have announced their intention to marry. The two families grudgingly agree to attend the wedding and banquet. But, they insist upon being seated at opposite sides of the banquet hall. This leads to trouble at the buffet table.

The table contains a series of plates with different types of food. The Hatfields insist on proceeding from left to right along the buffet table, The McCoys insist on proceeding in the opposite direction along the opposite side. Each guest takes some food from each plate before passing to the next. It is possible that a plate could be empty: either another family member or an enemy on the other side of the table took the last piece. If a plate is empty, then that guest simply stands and waits until sufficient food is available.

As each guest leaves the buffet, they join the rest of their family to celebrate. But, due to the tension at the event, no-one is able to eat. So, each guest eventually slips back over to the buffet table and returns all of his/her food to the plates without waiting for anyone else. (How gross!) Seeing nothing else to do, each guest gets back in line. After enough trips through the buffer, each guest will become tired and go home.

Of course, there is a problem here. If the right sequence of events occurs, the party will deadlock and never end. Even if there is no deadlock, it is possible that some guests will wait indefinitely and starve. (no pun intended.) Both of these can be avoided if the host of the party carefully controls access to the buffet table.

The Battling Buffet Problem

Let's formalize this a little and call it the Battling Buffet Problem.

There are N plates, each containing an integral number of items. There are G guests. The even-numbered guests start at plate 0 and move to higher-numbered plates. The odd-numbered guests start at plate N-1 and move toward the low numbers. Guests may move at different speeds, so they do not necessarily wait in line for each other. At each plate, a guest requests a random number of items. If that number is available, the guest atomically takes them and moves on to the next plate. If not, the guest takes nothing and waits until the desired number are available. After leaving the buffet table, each guest waits for a time, then returns all the food to the buffet and then starts in again. Note that items must be returned to the plate from which they were taken. Each guest makes a total of T trips through the buffet line, then stops.


Stop And Answer this Question:
Explain how deadlock can occur in the battling buffet problem.
Give an example with two guests and three plates.

The Buffet Simulation

This project does not require you to write a large amount of code. Rather, it requires you to think carefully and write a small amount of very precise code. Perhaps it would be better to call this a puzzle rather than a project.

Fortunately, we have already prepared a buffet for you! Download buffet.c and a Makefile to get started. Compile the code and run it as follows:

% make
% ./buffet 10 deadlock
This indicates that the simulation should be run with 10 threads in the deadlock mode. As you may guess, this means that the simulation is likely to deadlock. You might have to run it several times before you observe a deadlock. Once you see the output stop, press Control-C to abort the program. The program also accepts the modes single, multi, and fair. You must modify the code to support each of these modes as described below.

The code is simple and is structured as follows. main parses the arguments and creates a number of threads. Each thread runs the function guest_thread, which simulates the behavior of the guests described above. Each guest calls buffet_get to get or return items from each plate. Each call to buffet_get includes the plate number, the number of items to get, and the ID of the calling thread. To return items, each guest calls buffet_put with similar arguments.

The existing buffet_get and buffet_put are woefully inadequate. In fact, they are broken in three distinct ways. 1. They do not prevent multiple threads from corrupting the plate[] array via simultaneous access. 2. They use busy-waiting when no resources are available. 3. They allow for deadlocks to occur.

Your job is to modify buffet_get and buffet_put in order to allow every thread to run safely to completion without deadlocking or busy waiting. To make the problem interesting, the only functions that you may modify are buffet_get and buffet_put. Of course, you can add helper functions, global variables, and the like, but you cannot modify any of the existing functions. You must live with the unusual behavior of the guests. We really mean this, so it is worth repeating:


The only functions that you may modify are buffet_get and buffet_put.

Synchronization Algorithms

You must build three solutions to this synchronization problem, each corresponding to the modes single, multi, and fair. Your program will contain all three solutions; the method will be chosen by the command-line arguments. You should use a monitor (mutex and condition variables) to solve this problem, as described in the book. Take some time to think carefully about each solution before you begin to code. Here are some hints and notes on each.

single - A simple (but inefficient) solution to this problem is to allow one guest to select items from the buffet at a time. However, this solution will take quite some time to run.

multi - A better solution would allow multiple guests to walk the buffet line at once. Of course, you can't allow all of the guests in at one time, because the system will deadlock. Figure out some subset of the guests that are safe to let in together. In this mode, it's OK if some of the guests have to wait a long time before eating. This soution should run considerably faster than single. Compare the run-time of the two to make sure this happens.

fair - The previous two modes do not guarantee any fairness in access to the buffet. In this mode, the already-volatile guests will cause trouble if any one waits more than five seconds for service. Invent a solution that provides the good performance of multi, but ensures that no guest will wait forever for service. This solution should run slightly slower than multi, but still considerably faster than single. (Note: We have already implemented this behavior of the guests; your job is to make the buffet accommodate their behavior.)

Handing In

Turn in your modified buffet.c to your dropbox. Please review the general instructions for assignments.

This project is due on Thursday, March 8th at 11:59pm. Late assignments are not accepted.

The grade on this project will take into account the correctness of your program in the single (50%), multi (30%), and fair (10%) modes, as well as good coding style (10%). No credit will be given for any mode that crashes or deadlocks. 50% of the total grade will be deducted if you modify any function other than buffet_get or buffet_put.