Gotchas
Below is a list of errors that have been found in previous attempted solutions
to this programming problem.  Avoid these errors.  
 
-  ERROR: a delay of the form:
     for (i=0; i < delay; i++) sched_yield();
     is added to a program to "fake" synchronization.  The program produces
     incorrect output if the line of code is removed, or if other delays are
     introduced.  Neither adding nor removing delays should affect the
     correctness of the program. 
 -  ERROR: A user thread finds that the buffer it has chosen is not available
     so it just "gives up" and copies its packet into the other buffer
     instead.  This is not allowed.  The user chooses one of the buffers with
     this line of code:  
     protocol = (random() % 2 ) ; 
     The user is then required to utilize that particular value of "protocol"
     and to put its packet into pktBuf[protocol].
 -  ERROR: The program employs busy waiting for synchronization.  For example
     a loop of the form (using pseudo-code):
     "while (some flag is false) do nothing" 
     This is very bad.  The waiting process wastes CPU time.  Another process
     that wants to change the flag from false to true could be delayed from
     doing that because the first process is keeping the CPU busy executing
     its loop.
 -  ERROR: The program uses a flag for synchronization but the flag is not
     protected with a semaphore.  Any flag that is used by more than one
     thread is a shared variable.  It isn't likely that shared variables can
     be used correctly without protection. 
 -  ERROR: A thread that locks too much data is probably wrong.  For example
     suppose a user thread blocks access to both buffers while using only one
     of the buffers.  That is inefficient.  On a multiprocessor it should be
     possible for two buffers to be in use at the same time.  The program
     should allow sharing when there is no danger of incorrect results.