# CS140 Problem Set 0: Synchronization

Due: Thursday, January 24, 2013, 11:59 PM

Note: this problem set should be done individually, not in teams. The teams will apply to the four Pintos projects. For this problem set it is OK to discuss general strategy with other people, and it's OK to give and receive help tracking down problems, but you must write your own code.

## Problem 1: CalTrain Automation

CalTrain has decided to improve its efficiency by automating not just its trains but also its passengers. From now on, passengers will be robots. Each robot and each train is controlled by a thread. You have been hired to write synchronization functions that will guarantee orderly loading of trains. You must define a structure `struct station`, plus several functions described below.

When a train arrives in the station and has opened its doors, it invokes the function

`station_load_train(struct station *station, int count)`

where count indicates how many seats are available on the train. The function must not return until the train is satisfactorily loaded (all passengers are in their seats, and either the train is full or all waiting passengers have boarded).

When a passenger robot arrives in a station, it first invokes the function

`station_wait_for_train(struct station *station)`

This function must not return until a train is in the station (i.e., a call to `station_load_train` is in progress) and there are enough free seats on the train for this passenger to sit down. Once this function returns, the passenger robot will move the passenger on board the train and into a seat (you do not need to worry about how this mechanism works). Once the passenger is seated, it will call the function

`station_on_board(struct station *station)`

to let the train know that it's on board.

Create a file `caltrain.c` that contains a declaration for `struct station` and defines the three functions above, plus the function `station_init`, which will be invoked to initialize the station object when CalTrain boots. In addition:

• You must write your solution in C using the Pintos functions for locks and condition variables:
```lock_init (struct lock *lock)
lock_acquire(struct lock *lock)
lock_release(struct lock *lock)
cond_init(struct condition *cond)
cond_wait(struct condition *cond, struct lock *lock)
cond_signal(struct condition *cond, struct lock *lock)
cond_broadcast(struct condition *cond, struct lock *lock)```
Use only these functions (e.g., no semaphores or other synchronization primitives).
• You may not use more than a single lock in each `struct station`.
• You may assume that there is never more than one train in the station at once, and that all trains (and all passengers) are going to the same destination (i.e. any passenger can board any train).
• Your code must allow multiple passengers to board simultaneously.
• Your code must not result in busy-waiting.

## Problem 2: Chemical Reaction

You have been hired by Mother Nature to help her out with the chemical reaction to form water, which she doesn't seem to be able to get right due to synchronization problems. The trick is to get two H atoms and one O atom together at the same time. Each atom is represented by a thread. Each H atom invokes the function

`void reaction_h(struct reaction *r)`

when it is ready to react, and each O atom invokes the function

`void reaction_o(struct reaction *r)`

You must write the code for these two functions. The functions must delay until there are at least two H atoms and one O atom present, and then exactly one of the functions must call the procedure `make_water` (which you needn't write; Mother Nature's already gotten this part figured out). After each `make_water` call two instances of `reaction_h` and one instance of `reaction_o` should return.

Create a file `water.c` that contains the functions `reaction_h` and `reaction_o`, along with a declaration for `struct reaction` (which contains all the variables needed to synchronize properly). In addition:

• Write the function
`reaction_init(struct reaction *r)`
which will be invoked to initialize the reaction object.
• Your code must invoke `make_water` exactly once for every two H and one O atoms that call `reaction_h` `reaction_o`, and only when these calls are active (i.e. the functions have been invoked but have not yet returned).
• Write your solution in C using the Pintos functions for locks and condition variables listed in Problem 1 above.
• You may not use more than a single lock in each `struct reaction`.
• Your code must not result in busy-waiting.

We have created a test framework that you can use to test your code on Unix-like systems such as the myth cluster and Mac OS X. To use the framework, download the file cs140-ps0.tar. Then extract its contents with the command

`tar xf cs140-ps0.tar`

This will create a directory `cs140-ps0`. Read the `README` file in that directory for instructions on how to use the testing framework.

## Complexity Penalty

Synchronization code is hard to get right, so it's important that it be clean, simple, and obvious. Unfortunately, solutions to this problem set often end up long and complicated; such solutions rarely work, and in real life they would be brittle and hard to maintain. If the CAs judge your code to be unnecessarily long and complicated, they will deduct up to 30% of the total score for this. Our solution for `caltrain.c` has 51 lines and our solution for `water.c` has 36 lines (not including comments). Note: your goal should be simplicity, not just line count; simple programs are usually shorter than complex ones, but the shortest program isn't always the simplest.

## Submitting this Problem Set

To submit your solutions, `cd` to the directory containing `caltrain.c` and `water.c`, then type the following commands:

```make clean
/usr/class/cs140/bin/submit 0```