ICS412 - Fall 2009 - Programming Assignment #3 -

Work alone
You are expected to do your own work on all homework assignments. You may (and are encouraged to) engage in general discussions with your classmates regarding the assignments, but specific details of a solution, including the solution itself, must always be your own work. (See the statement of Academic Dishonesty on the course's syllabus.)

What to turn in?
Turn in an archive (.zip, .tar, .tar.gz, .tgz, etc.) that contains: The archive must be turned in via e-mail to henric@hawaii.edu and to altunkay@hawaii.edu with a subject line like "ICS412: PA#3" before 11:59PM on the day the assignment is due.


Exercise #1 (20 pts): A tree of pthreads
Write a Pthread program, called tree_of_pthreads, that creates a p-ary tree of threads of depth d (p > 0, d > 0). Each thread, when created, prints its lineage, creates p children threads, and then waits for its p children threads to complete. Each leaf thread just prints its lineage followed by a '*'.

The lineage of a thread consists of the child index of its ancestors and of itself. Index start at zero. For instance, if a thread is the second child of the fourth child of the third child of the root thread, then its lineage is printed as "2 3 1". If this thread is a leaf thread, then its lineage is printed as "2 3 1*". Your code should take p and d as command-line arguments, in this order, and handle command-line errors.

Below are example execution outputs:

% ./tree_of_pthreads foo 4
'foo' is an invalid arity argument

% ./tree_of_pthreads 3 4 5
Usage: tree_of_pthreads <arity> <depth>

% ./tree_of_pthreads 1 0
'0' is an invalid depth argument

% ./tree_of_pthreads 1 1
Lineage = 0 *

% ./tree_of_pthreads 2 1
Lineage = 0 *
Lineage = 1 *

% ./tree_of_pthreads 1 2
Lineage = 0
Lineage = 0 0 *

% ./tree_of_pthreads 2 2
Lineage = 0
Lineage = 1
Lineage = 0 0 *
Lineage = 0 1 *
Lineage = 1 0 *
Lineage = 1 1 *

% ./tree_of_pthreads 2 3
Lineage = 0
Lineage = 1
Lineage = 0 0
Lineage = 0 1
Lineage = 1 0
Lineage = 1 1
Lineage = 0 0 0 *
Lineage = 0 0 1 *
Lineage = 0 1 0 *
Lineage = 0 1 1 *
Lineage = 1 0 0 *
Lineage = 1 0 1 *
Lineage = 1 1 0 *
Lineage = 1 1 1 *

Exercise #2 (5 pts): Pthread Synchronization
Consider the Pthread implementation of producer/consumer with a bounded stack in prod_cons_bogus.c. This implementation was written by a co-worker of yours who had no idea that synchronization is an issue in multi-threaded programs. The code employs busy waits and does not deal with any critical section. Four lines are added to the code to print a '!' whenever one can tell there was a problem due to a race condition (however, the very statements that print out the '!' are themselves subjected to race conditions!) This code may not even terminate and instead deadlock. Yeah. it's a mess.

Copy this implementation into a file called prod_cons_cond.c, which generates executable prod_cons_cond. This new implementation should address all synchronization issues using locks and condition variables as provided by Pthreads. Use only one (shared) lock and one (shared) condition variable. This really isn't difficult given what was said in class, but at least gets you writing some code with Pthread mutexes and condition variables.


henric@hawaii.edu