Concurrency Mutual Exclusion and Synchronization

Document Sample
Concurrency Mutual Exclusion and Synchronization Powered By Docstoc
					Concurrency: Background and

                            Fred Kuhns

   Department of Computer Science and Engineering
         Washington University in St. Louis

                           WASHINGTON UNIVERSITY IN ST LOUIS
              Origins of Concurrency
• Processes need to communicate, issues:
  – How is information exchanged between
    processes (shared memory or messages)?
  – How to prevent interference between
    cooperating processes (mutual exclusion)?
  – How to control the sequence of process
    execution (conditional synchronization)?
• Execution of the kernel (interrupts,
  exception, traps) often results in the need
  for concurrent access to state and
  deferred processing pending an event.

   Fred Kuhns ()                                2
        Problems – Shared Memory
• Concurrent programs may exhibit a dependency
  on process/thread execution sequence or
  processor speed (neither are desirable!)
  – race condition – who’s first, and who goes next.
    affects program results.
• There are two basic issues resulting from the
  need to support concurrency:
  – Mutual exclusion : ensure that processes/threads do
    not interfere with one another, i.e. there are no race
    conditions. In other words, program constraints
    (assumptions) are not violated.
  – Conditional synchronization : Processes/threads must
    be able to “wait” for the data to arrive or
    constraints (assertions) to be satisfied.
   Fred Kuhns ()                                        3
• Consider a process as a sequence of statements
  which are implemented as one or more primitive
  atomic operations (hardware instructions)
• Concurrent program results in the interleaving of
  statements from different processes
• Program state is value of variables at a given point
  in time. Execution viewed as a sequence of states
  si,. Atomic actions transform states.
• Program history is sequence of states:
  s0 -> s1 -> ... -> sN
  – Synchronization constrains the set of possible histories
    to only those that are desirable
• Mutual Exclusion combines a sequence of actions
  into a critical section which appear to execute
     Fred Kuhns ()                                       4
          Race Conditions - Example
• There are 4 cases:
  – case 1: task A runs to completion
    first loading y=0, z=0.              Example 1
    x=0+0=0                              int y = 0, z = 0;
  – case 2: Task B runs and sets y to 1, Task A { x = y + z}
    then Task A runs loading y=1 and     Task B {y = 1; z = 2}
    z=0.                                 Results:
    x=1+0=1                              x = {0, 1, 2, 3}
  – case 3: Task A runs loading y=0,     load y into R0
    then Task B runs to completion,      load z into R1
    then Task A runs loading z=2.        set R0 = R0 + R1
    x=0+2=2                              set R0 -> x
  – case 4: Task B runs to completion,
    then Task A runs loading y=1, z=2,
    Fred Kuhns ()                                         5
        Race Condition: OS Example

   Task A:                      Task B:
   ...                          ...
   get KFT_NextFree (7)
   -- preempted –-              get KFT_NextFree (7)
                                KFT_NextFree += 1;
                                update Entry 7
   KFT_NextFree += 1;           -- preempt
   update entry 7

                                                       Kernel File Table
                              KFT_NextFree = 7    0    myfile.c: attributes
                                                  1    myfile.o: attributes
• Final value of kernel table entry 7 is                        ...
                                                  7    NULL
• Final value of KFT_NextFree is 9
• Kernel File Table entry 8 is not allocated                    ...

     Fred Kuhns ()                                                            6
              At-Most-Once Property
• Definitions:
  – Independent processes: Two processes are independent
    if the write set of each is disjoint from both the read
    and write sets of the other.
  – Critical reference: reference to variable changed by
    another process.
• At-Most-Once property: If the assignment stment
  (x = e) satisfies (1) e contains at most one critical
  reference and x is not read by another process or
  (2) e contains no critical references, in which case
  x may be read by another process.
  – there can be at most one shared variable and it can be
    referenced at most once.
• If (x = e) satisfies AMO then it appears to be
    Fred Kuhns ()                                       7
               Critical Section Problem
Entry/exit protocol satisfies:
1. Mutual Exclusion:
   At most one in CS
2. Absence of deadlock/livelock:    Task A {
   2 or more threads then at          while (True) {
   least one enters CS.                 entry protocol;
3. Absence of Unnecessary delay:        critical section;
   Only 1, then it must entry:          exit protocol;
   other threads not in CS or
                                        non-critical section;
   have terminated.
4. Eventual entry:
   thread can’t wait forever – no
   starvation. May be influenced
   by scheduling policy.

     Fred Kuhns ()                                        8
  Mutual Exclusion – Busy waiting
• Interrupt disabling:
  – Process runs until requests OS service or
  – Process disables interrupts for MUTEX
  – Processor has limited ability to interleave
  – Efficiency of execution may be degraded
  – Multiprocessing
     • disabling interrupts on one processor will
       not guarantee mutual exclusion

   Fred Kuhns ()                                    9
Mutual Exclusion: Help from Hardware
      (Return original value of lock)
      boolean Test&Set (boolean &lock) {
           boolean tmp = lock;
           lock = True;
           return tmp;
You have the lock iff False is returned
 – if lock == False before calling TSL(lock)
    • it is set to True and False is returned
 – if lock == True before calling TSL(lock)
    • it is set to True and True is returned
  Fred Kuhns ()                                 10
         Mutual Exclusion with TSL
• Shared data:
       boolean lock = False; // initialize to false
• Task Pi
  do {
       // Entry protocol
       while (TSL(lock) == True) ; // spin: wait for lock
       // execute critical section code
       -- critical section --
       // Exit protocol
       lock = False;
       // Non-critical section code
      -- remainder section --
  } while (1);
    Fred Kuhns ()                                           11
                   Machine Instructions
• Advantages
  – Applicable multiple processes on single or multi-
    processor systems (using shared memory)
  – It is simple and therefore easy to verify
  – It can be used to support multiple critical sections
• Disadvantages
  – Busy-waiting consumes processor time
  – Starvation possible when a process leaves a critical
    section and more than one process is waiting.
      • Who is next?
  – Deadlock - If a low priority process has the critical
    region (i.e. lock) but is preempted by a higher priority
    process spinning on lock then neither can advance.
   Fred Kuhns ()                                           12
         Must we always busy wait?
• While busy waiting is useful in some situations
  it may also lead to other problems: inefficient
  use of CPU and deadlock resulting from a
  priority inversion
• What we really want is a way to combine
  mutual exclusion schemes with conditional
• In other words, we want the option of blocking
  a process until it is able to acquire the mutual
  exclusion lock.
• Simple solution is to add two new functions:
  – sleep() and wakeup()

   Fred Kuhns ()                                 13
  Adding Conditional Synchronization
                          int N 10
                          int buf[N];
                          int in = 0, out = 0, cnt = 0;

Task producer {                          Task consumer {
  int item;                                item_t item;
  while (TRUE) {                           while (TRUE) {
    item = mkitem();                         if (cnt == 0) sleep();
    if (cnt == N) sleep();                   item = buf[out];
        buf[in] = item;                      out = (out + 1) % N;
    in = (in + 1) % N;
                                             if (cnt == N-1)
    if (cnt == 1)
        wakeup(consumer);                       wakeup(producer);
  }                                          consume(item);
}                                          }
    Fred Kuhns ()                                                      14
                  Lost wakeup problem
• Assume that the lock() and unlock()
  functions implement a simple spin lock.
• There is a race condition that results in
  a lost wakeup, do you see it?

  Fred Kuhns ()                               15
                    Intro to Semaphores
• Synchronization mechanism:
  – No busy waiting and No lost wakeup problem.
• Integer variable accessible via two indivisible
  (atomic) operations :
  – P(s) or wait(s):
     If s > 0 then decrement else block thread on semaphore queue
  – V(s) or signal(s):
    if s <= 0 then wake one sleeping thread, else increment s.
• Each Semaphore has an associated queue.
• Can define a non-blocking version of wait(s).

    Fred Kuhns ()                                              16
             Critical Section of n Tasks
• Shared data:
   semaphore mutex; // initialize mutex = 1

• Process Ti:

  do {
           -- critical section --
        -- remainder section –
  } while (1);

   Fred Kuhns ()                              17
       Semaphore Implementation
• Define a semaphore as a record
 typedef struct {
    int value;  // value of semaphore
    queue_t sq; // task/thread queue
 } semaphore;
• Assume two simple operations:
  – block suspends the task/thread that invokes
  – wakeup(T) resumes the execution of a blocked
    task/thread T.
   Fred Kuhns ()                             18
          Implementation - Threads
void wait(sem_t *S)           void signal(sem_t *S)
{                             {
    S->value--;                   thread_t t;
    while (S->value < 0) {        S->value++;
          addthread(S->sq);       if (S->value £ 0) {
          sleep();                    t = getthread(S->sq);
    }                                 wakeup(t);
    return;                       }
}                                 return;
    Fred Kuhns ()                                       19
     Some Reference Background
• Semaphores used in Initial MP implementations
• Threads are woken up in FIFO order (convoys)
  – forcing a strictly fifo order may result in unnecessary
• Used to provide
  – Mutual exclusion (initialized to 1)
  – Event-waiting (initialized to 0)
  – Resource counting (initialized to number

   Fred Kuhns ()                                        20

Shared By: