Lecture 7

Review -- key points on semantics of concurrent programs

   assertions -- predicates that are true at points in a program

   interference -- statements in one process invalidating assertions in another

   avoiding interference
      disjoint variables   -- independent parts
      weakened assertions  \
      global invariants     | overlapping parts (process interaction)
      synchronization      /


Safety and Liveness Properties (Section 2.8)

   safety -- nothing bad ever happens (=> no bad states)

   liveness -- something good eventually happens  (=> progress)

   Producer/Consumer problem revisited -- proof outline in Figure 2.4

      mutual exclusion  (p==c and p>c) == false
         this is an instance of a general method called
         Exclusion of Configurations

      progress -- assuming await statements get a chance
         proving liveness properties requires a stronger logic (e.g., temporal)


The Critical Section Problem (Section 3.1)
   [the CS problem, or is it even "the" CS (Computer Science) problem?]

   what?  implementing (often large) atomic actions in software

   why?  linked lists in OSs, database records, counters (homework 1b), etc.

   example -- ready list in an OS (or the SR RTS)

      diagram on board showing structure
      new process -- add descriptor to tail of list
      free processor -- remove descriptor from front of list

      add and remove have to be atomic.  Why?  (they manipulate two links)

   implementing atomic actions

      machine instructions       basic building block
      disable interrupts         kernel of an OS on a processor
      spin locks (busy waiting)  multiprocessor OS or parallel program
      blocking primitives        higher-level parts of an OS or
        (e.g., semaphores)         multithreaded programs

      we are going to see now how to implement spin locks; later we will
      look at blocking primitives.


Model for CS Problem

   process CS[i = 1 to n] {
     while (true) {
       CSenter:  entry protocol;
       critical section;
       CSexit:  exit protocol;
       noncritical section;
     }
   }

   specifying mutual exclusion

      int in[1:n]   # initially all zero

      in[i] = 1 when process i is in its critical section

      at all times require
         MUTEX:  0 <= sum of in[i] <= 1

      add assignments to in[i] to the above code outline and use
      an await statement to ensure the MUTEX is a global invariant

   how to implement << await (sum in[i] == 0) in[i] = 1; >> in above program

      change variables; let mutex = 1 - (sum in[i])
      initially mutex == 1; at all times want 0 <= mutex <= 1

      use this change of variables to modify the above code, getting

         << await(mutex == 1) mutex--; >>
         critical section;
         << mutex++ >>

       mutex is a semaphore and these statements are the P() and V() operations
       (See Chapter 4 in the text book and Chapter 8 in the SR book)

       [Note:  I introduced this simple use of semaphores now so they could
        use it in their programming assignment.]


Spin Locks (Section 3.2)

   semaphores are special primitives; nontrivial implementation (see Chap 6)
   how can we solve the CS problem using machine instructions directly?

   observation -- there are only 2 key states:
      nobody is in its CS  --  lock == false
      somebody is in its CS --  lock == true

   Using just lock, we get the following code:

      << await (!lock) lock = true; >>
      critical section
      lock = false;      # angle brackets not needed.  why?

      Figure 3.2

   This still uses an await statement, but it is very simple
   All modern machines provide some way to implement this kind of spin lock


Test and Set

   the first instruction for implementing spin locks (IBM, mid 1960s)

   bool TS(bool lock) {           # an atomic instruction
      << bool initial = lock;
         lock = true;
         return initial; >>

   using TS, we get the following simple solution

      CSenter: while (TS(lock)) skip;

      CSexit: lock = false        # simply reinitialize

   explain why this is called a spin lock

   brief explanation of properties (details next time):

      mutual exclusion
      absence of unnecessary delay     (with weakly fair scheduling)
      absence of livelock (deadlock)   (with weakly fair scheduling)
      but not fair -- no GUARANTEE of eventual entry