Lecture 5

Review -- finding patterns in a file using two processes

  (a) "co inside while"     (b) "while inside co"

       outline of code           outline of code

  synchronization:
     (a)  provided by co ... oc
     (b)  need to program it; today we'll see how
          the requirements are alternating access and detecting termination


Example  (I mix between using SR and C/book notation)

   int x = 0, y = 0, z;

   P1::   x = 1;               P2::  y = 2;
          z = x+y;                   z = x-y;

   what are the final values of x, y, and z?
   have the class help out
   answer depends on execution order and what is atomic


States, Actions, etc.  (Section 2.1)

   state -- values of variables at a point in time

   atomic action -- indivisible state change
      hardware:  load, store, add, ...
      software:  critical sections (Chapter 3)

   history -- a trace of ONE execution; an interleaving of atomic actions

   property -- an attribute of ALL histories of a program, e.g., correctness

   today:  understanding states and actions
   next time:  proving properties in a programming logic

   How many histories are there in a program with n processes and
   m atomic actions per process?

      (n m)! / (m!)**n    if n = 2 and m = 4, this is 70 histories!


Synchronization (Section 2.3) -- restricts the number of histories

   Given array a[1:n] of positive integers

   Find the maximum value m by examining all elements in parallel
   [this is an example of an accumulation or reduction problem]

   Goal -- expressed as a predicate

       (for all j : 1 <= j <= n : m >= a[j])  and
       (there exists j : 1 <= j <= n : m = a[j])

   Program outline

      var m := 0
      process FindMax(i := 1 to n)
         body
      end


Program 1 for body -- no synchronization (hence no constraints)

   if a[i] > m -> m := a[i] fi

   what is true before and after this statement?
   what is wrong with this program?  (interference)
   what's the most that we can say?  (m is SOME a[i])


Program 2 for body -- make it a single atomic action (overconstrained)

   < m -> m := a[i] fi>>

   the program is now correct, but the processes are serialized

   comment on the angle bracket notation
   also comment on how this program is not the same as a sequential
   program, because the processes could execute in any order (although
   they will do so one at a time)


Program 3 for body -- use smaller atomic actions

   if a[i] > m ->
      < m -> m := a[i] fi>>
   fi

   What's true now before and after the outer if statement?  Why?

   This technique is called "double checking".  It may not seem like
   we have accomplished much, but in fact we have.  We'll actually
   see this technique put to realistic use later.  (In fact, access
   to an Ethernet works kind of like this.)


Atomic Actions (Section 2.4)

   fine grained -- reads and writes of simple variables (loads/stores)

   coarse grained -- programmed using << ... >> or real code (in Chap 3)

      << S; >>    execute statement list S indivisibly

      << await(B); >>  wait for B to be true

      << await(B) S; >>  wait for B to be true, then execute S
                         AS A SINGLE ATOMIC ACTION

   examples of the use of await statements

      << s = s+1; >>
      << await (s>0) s = s-1; >>

      these are semaphore operations as many of you might recognize

   at-most-once property

      << S; >>  ==  S;  as long as S contains at most one critical reference,
            that is a reference to a variable changed by another process
      
      in this case, you cannot tell the difference, so S will appear to
      execute atomically

      << await(B); >>  ==  while (not B) ;  if B contains at most one
                                            critical reference


Producer/Consumer example to put all this together (Section 2.5)

   problem:  copy a[n] in Producer to b[n] in Consumer using a single
             shared buffer

             use synchronization to alternate access to the buffer

   sketch the idea of the problem and solution, then present the
   code in Figure 2.2.  (See figures section of these Web pages)

   comment on synchronization code; mention that this specific code
   can be implemented using busy waiting while loops because each
   await statement contains only