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.