CSCI 340: Operating Systems
Spring 2005
Program 4: Multi-Thread Bridge Simulator
Due: Midnight Friday
December 9
(this is the last week of classes)
Grading
Weight: 3
Overview:
A two-lane north-south road contains a one-lane bridge. A
southbound (or northbound) car can use the bridge only if there are no
oncoming cars when the car arrives at the bridge. In order to
prevent accidents, two traffic lights (one at the north end, one at the
south end) have been installed on the bridge. Write a program
that simulates the traffic lights and cars crossing the bridge.
You may work by yourself or with one other student. You may
work
in a group even if you have done the other assignments independently.
Only one person from each group should turn in the
assignment. Put both names and ecst usernames at the top of
your file.
Requirements:
Write a single program (you can put it in a single file such as
bridge.cpp or bridge.c) that creates three types of threads:
- A
main() thread that start the
simulation and determines when the simulation is over.
- One
car generating thread that generates the
specified number of cars at random intervals.
- Many
car threads each of which
simulates a
single car.
Input:
The
bridge
program must take two
required command line arguments and a third optional argument.
The first is the number of northbound
cars, the second is the number of southbound cars, the third is a seed
for the random number generator. For example:
% bridge 100 10 42
Will
result in
a simulation with
100 northbound cars, 10 southbound cars, and will seed the random
number generator with 42. If the third argument is not given,
seed the random number generator using the clock.
Output:
Messages
should
be written to
standard out every time:
- A
car arrives at the
bridge
- A
car starts driving
over the bridge
- A
car exits the bridge
- A
signal changes color.
For example, the output from
a simulation with 2 northbound
cars
and 1 southbound car might look like this:
N
red
S green
N1 arrived
S red
N green
N1 enters
S1 arrived
N2 arrived
N2 enters
N1 exits
N2 exits
N red
S green
S1 enters
S1 exits
Simulation over
Output
the
exact same messages as
this example.
Simulation Details:
Each
car must
take a random
amount of
time on the bridge. You can use one of the UNIX random
functions
and one of the UNIX sleep functions to implement this.
Label the cars N1, N2, .. Nn, S1, S2, ..., Sm, where n is the number of
northbound cars and m is the number of southbound cars.
Multiple cars may be on the bridge at any time, as long as all the cars
are going in the same direction.
Cars cannot pass each other on the bridge. In other words, a
car
cannot exit the bridge before all the cars in front of it have exited
(all cars that entered the bridge
before it).
Cars should not have to wait if there is no opposing traffic.
The actions of the cars should obey the traffic lights. For
example, if the northbound light is red, no northbound cars should
enter the bridge. However,
it is possible that a northbound car is still on the bridge when the
north light turns red, just make sure the south light doesn't turn
green before all the northbound cars are off the bridge.
The creation of northbound cars should
be randomly distributed over the entire duration of the simulation.
The creation of the southbound cars should also be randomly
distributed over the entire duration of the simulation. For
example,
if there are 100 northbound cars and 10 southbound cars, it should be a
very unlikely event that the first 20 cars contain 10 northbound and 10
southbound cars. It would be more likely that the first 20
cars
contain 18 northbound cars and 2 southbound cars.
Implementation Details:
Use
semaphores
to provide thread
synchronization.
Do not use busy waits.
Use the POSIX pthread library to create the threads.
Use GNU gcc or g++ to compile your program.
You may implement your program in the cygwin environment, OS X, or
Linux. If you use OS X and it does not work
on
my Linux machine, you will have to bring your OS X machine to my office
and demonstrate the program.
Hints:
I recommend writing a simple two-thread program that uses a semaphore
to synchronize the processes before you start on this
program. After you learn how semaphores and threads
work, work on the
algorithmic portion of the assignment. You may use my pthread.cpp as a starting
point. void.cpp
gives an example of using void pointers to pass arguments to
thread functions.
You can distribute
the creation of
north and south cars by calculating the ratio of north cars to total
cars and then generating a number between 0-1. If the number
is
less than the north-total_car ratio then generate a north
car. If
it
is greater then the ratio generate a south car. However, you
must
not generate cars once you have reached the max (that is, if there are
10 south cars and you have already created 10 south cars, all the rest
of the cars must be north).
If you use the C/C++ random() function, you will always get the same
series of numbers. Thus every time you run your program you
will
get the same simulation. A real simulation should be
different
every time. To make random() generate a new series of numbers
each time you run your program, you have to set its seed. An
easy way to do
this is to
use the current time. Since time never repeats itself, you
will
get a new seed each time:
srandom(time(0));
The problem with this
approach is
that it is very hard to debug a program when it generates different
random numbers each time you run it. Thus you don't want to
seed using the clock while debugging. As an
alternative, an optional
command
line argument can be used as the seed. Specifically, if there
is a 4th
command line argument use it as the seed, otherwise use the clock.
This will allow you to experiment during debugging and find
seeds that test specific features.
if
(argc == 4)
srandom(atoi(argv[3]));
else srandom(time(0));
You may use the car threads
to control the signals. If you do the extra credit you may
find it easier if there is one (or more) dedicated process(es) to
control the signals.
Extra
Credit
(10%)
Modify your solution so that cars are
not starved. For
example, northbound cars should not monopolize the bridge if there are
southbound cars waiting.
However, northbound and southbound cars should not just take
turns. When several cars are waiting to go in one direction,
more
than one car should cross the bridge, but the car in the other
direction should not have to wait for all the cars to cross.
If
you do
the extra credit, turn in an ASCII text file called algorithm, that
describes
the algorithm you used to control how cars cross the bridge.
Include an explanation on how you prevent starvation.
Simulation
Viewer:
I've written a program called sim_viewer that graphically displays the
output from the bridge simulator program. It is in the src/sim_viewer
directory. You can
download sim_viewer.tar.
The Makefile supports Linux, Cygwin, and OS X, but you have to comment
in/out the appropriate libraries. Read the comments in the
Makefile.
Your program must output the messages exactly as described in the
project description for the viewer to work.
You can pipe the output from your program directly to the
viewer:
% bridge 5 3 | sim_viewer. Or you can save the output of your
program to a file and then direct it into sim_viewer:
%
bridge 10
3 > test01.out
% sim_viewer
< test01.out.
I've provided two sample input files in src/sim_viewer: input.good and
input.bad.
Since sim_viewer uses a graphics window, you cannot use it over telnet
or putty.
You must install OpenGL and the glut library on your machine to use
sim_viewer. If you run cygwin.exe you can choose to install
OpenGL from the graphics menu. Newer versions of cygwin
include the glut library.
On OS X you must reference the OpenGL and GLUT packages when linking.
How
to
turn in code:
Turn
in all the files necessary to make
your program
work including a Makefile. My solution contains the files:
bridge.cpp
Makefile
copy your
files to the turn in directory for this
assignment.
See How
to turn in assignments for
details on turning in assignments.
If you
are working with someone, only turn in one copy of the
assignment. It is very helpful is people working together
always
turn their assignments in under the same name. Make sure you
list
both names at the top of all files.
Late
assignments:
You
will lose 10% for each 24 hours your assignment is late.
e-mail late assignments to me (create a .tar file for all your files
and e-mail the .tar file to me)
It may take me much, much longer to grade late assignments (if I have
already graded the other assignments, grading late assignments gets a
low priority).
I use the time I receive your e-mail, not the time you send your e-mail
as the turn in time (sometimes e-mail from an ISP takes a day or
two). If you want to be absolutely sure your assignment gets
to me immediately, e-mail it from your ecst account (use your browser
(webmail.ecst.csuchico.edu) to e-mail the file to me).