Process Synchronization: Silberschatz, Galvin and Gagne ©2013 Operating System Concepts - 9 Edition
Process Synchronization: Silberschatz, Galvin and Gagne ©2013 Operating System Concepts - 9 Edition
Operating System Concepts – 9th Edition   Silberschatz, Galvin and Gagne ©2013
                     Chapter 5: Process Synchronization
              Background
              The Critical-Section Problem
              Peterson’s Solution
              Synchronization Hardware
              Mutex Locks
              Semaphores
              Classic Problems of Synchronization
              Monitors
              Synchronization Examples
              Alternative Approaches
Operating System Concepts – 9th Edition     5.2      Silberschatz, Galvin and Gagne ©2013
                                          Objectives
               To present the concept of process synchronization.
               To introduce the critical-section problem, whose solutions can
                be used to ensure the consistency of shared data
               To present both software and hardware solutions of the
                critical-section problem
               To examine several classical process-synchronization
                problems
               To explore several tools that are used to solve process
                synchronization problems
Operating System Concepts – 9th Edition       5.3                    Silberschatz, Galvin and Gagne ©2013
                                          Background
              Processes can execute concurrently
                     May be interrupted at any time, partially completing
                      execution
              Concurrent access to shared data may result in data
               inconsistency
              Maintaining data consistency requires mechanisms to ensure
               the orderly execution of cooperating processes
              Illustration of the problem:
               Suppose that we wanted to provide a solution to the
               consumer-producer problem that fills all the buffers. We can
               do so by having an integer counter that keeps track of the
               number of full buffers. Initially, counter is set to 0. It is
               incremented by the producer after it produces a new buffer and
               is decremented by the consumer after it consumes a buffer.
Operating System Concepts – 9th Edition          5.4                    Silberschatz, Galvin and Gagne ©2013
                                          Producer
               while (true) {
                   /* produce an item in next produced */
Operating System Concepts – 9th Edition          5.5        Silberschatz, Galvin and Gagne ©2013
                                          Consumer
            while (true) {
                   while (counter == 0)
                           ; /* do nothing */
                   next_consumed = buffer[out];
                   out = (out + 1) % BUFFER_SIZE;
                           counter--;
                   /* consume the item in next consumed */
            }
Operating System Concepts – 9th Edition         5.6          Silberschatz, Galvin and Gagne ©2013
                                          Race Condition
                 counter++ could be implemented as
                            register1 = counter
                            register1 = register1 + 1
                            counter = register1
                 counter-- could be implemented as
                            register2 = counter
                            register2 = register2 - 1
                            counter = register2
                 Consider this execution interleaving with “count = 5” initially:
                     S0: producer execute register1 = counter                        {register1 = 5}
                     S1: producer execute register1 = register1 + 1                  {register1 = 6}
                     S2: consumer execute register2 = counter                        {register2 = 5}
                     S3: consumer execute register2 = register2 – 1                  {register2 = 4}
                     S4: producer execute counter = register1                        {counter = 6 }
                     S5: consumer execute counter = register2                        {counter = 4}
Operating System Concepts – 9th Edition             5.7                       Silberschatz, Galvin and Gagne ©2013
                              Critical Section Problem
               Consider system of n processes {p0, p1, … pn-1}
               Each process has critical section segment of code
                      Process may be changing common variables, updating
                       table, writing file, etc
                      When one process in critical section, no other may be in its
                       critical section
               Critical section problem is to design protocol to solve this
               Each process must ask permission to enter critical section in
                entry section, may follow critical section with exit section,
                then remainder section
Operating System Concepts – 9th Edition          5.8                    Silberschatz, Galvin and Gagne ©2013
                                          Critical Section
Operating System Concepts – 9th Edition          5.9         Silberschatz, Galvin and Gagne ©2013
                               Algorithm for Process Pi
do {
Operating System Concepts – 9th Edition          5.10   Silberschatz, Galvin and Gagne ©2013
                    Solution to Critical-Section Problem
             1. Mutual Exclusion - If process Pi is executing in its critical
                section, then no other processes can be executing in their
                critical sections
             2. Progress - If no process is executing in its critical section and
                there exist some processes that wish to enter their critical
                section, then the selection of the processes that will enter the
                critical section next cannot be postponed indefinitely
             3. Bounded Waiting - A bound must exist on the number of
                times that other processes are allowed to enter their critical
                sections after a process has made a request to enter its critical
                section and before that request is granted
                     Assume that each process executes at a nonzero speed
                     No assumption concerning relative speed of the n
                         processes
Operating System Concepts – 9th Edition       5.11                    Silberschatz, Galvin and Gagne ©2013
                          Critical-Section Handling in OS
              Two approaches depending on if kernel is preemptive or non-
              preemptive
                    Preemptive – allows preemption of process when running
                     in kernel mode
                    Non-preemptive – runs until exits kernel mode, blocks, or
                     voluntarily yields CPU
                     Essentially free of race conditions in kernel mode
Operating System Concepts – 9th Edition        5.12                   Silberschatz, Galvin and Gagne ©2013
                                          Peterson’s Solution
            Good algorithmic description of solving the problem
            Two process solution
            Assume that the load and store machine-language
             instructions are atomic; that is, cannot be interrupted
            The two processes share two variables:
                    int turn;
                    Boolean flag[2]
Operating System Concepts – 9th Edition          5.13              Silberschatz, Galvin and Gagne ©2013
                               Algorithm for Process Pi
               do {
                      flag[i] = true;
                      turn = j;
                      while (flag[j] && turn = = j);
                             critical section
                      flag[i] = false;
                             remainder section
                 } while (true);
Operating System Concepts – 9th Edition          5.14   Silberschatz, Galvin and Gagne ©2013
                               Peterson’s Solution (Cont.)
              Provable that the three CS requirement are met:
                 1. Mutual exclusion is preserved
                          Pi enters CS only if:
                                either flag[j] = false or turn = i
                 2. Progress requirement is satisfied
                 3. Bounded-waiting requirement is met
Operating System Concepts – 9th Edition           5.15               Silberschatz, Galvin and Gagne ©2013
                                Synchronization Hardware
            Many systems provide hardware support for implementing the
             critical section code.
            All solutions below based on idea of locking
               Protecting critical regions via locks
            Uniprocessors – could disable interrupts
               Currently running code would execute without preemption
               Generally too inefficient on multiprocessor systems
                    Operating systems using this not broadly scalable
            Modern machines provide special atomic hardware instructions
                    Atomic = non-interruptible
               Either test memory word and set value
               Or swap contents of two memory words
Operating System Concepts – 9th Edition   5.16                 Silberschatz, Galvin and Gagne ©2013
                      Solution to Critical-section Problem Using Locks
                  do {
                         acquire lock
                                critical section
                         release lock
                                remainder section
                  } while (TRUE);
Operating System Concepts – 9th Edition            5.17   Silberschatz, Galvin and Gagne ©2013
                                   test_and_set Instruction
            Definition:
                        boolean test_and_set (boolean *target)
                          {
                               boolean rv = *target;
                               *target = TRUE;
                               return rv:
                          }
         1. Executed atomically
         2. Returns the original value of passed parameter
         3. Set the new value of passed parameter to “TRUE”.
Operating System Concepts – 9th Edition     5.18                 Silberschatz, Galvin and Gagne ©2013
                          Solution using test_and_set()
           Shared Boolean variable lock, initialized to FALSE
           Solution:
                      do {
                          while (test_and_set(&lock))
                                   ; /* do nothing */
                                          /* critical section */
                              lock = false;
                                          /* remainder section */
                        } while (true);
Operating System Concepts – 9th Edition             5.19            Silberschatz, Galvin and Gagne ©2013
                        compare_and_swap Instruction
         Definition:
                  int compare _and_swap(int *value, int expected, int new_value) {
                        int temp = *value;
                        if (*value == expected)
                              *value = new_value;
                   return temp;
                  }
         1. Executed atomically
         2. Returns the original value of passed parameter “value”
         3. Set the variable “value” the value of the passed parameter “new_value”
               but only if “value” ==“expected”. That is, the swap takes place only under
               this condition.
Operating System Concepts – 9th Edition             5.20              Silberschatz, Galvin and Gagne ©2013
                    Solution using compare_and_swap
          Shared integer “lock” initialized to 0;
          Solution:
                       do {
                                while (compare_and_swap(&lock, 0, 1) != 0)
                                 ; /* do nothing */
                             /* critical section */
                       lock = 0;
                             /* remainder section */
                     } while (true);
Operating System Concepts – 9th Edition          5.21              Silberschatz, Galvin and Gagne ©2013
                Bounded-waiting Mutual Exclusion with test_and_set
             do {
                waiting[i] = true;
                key = true;
                while (waiting[i] && key)
                        key = test_and_set(&lock);
                  waiting[i] = false;
                  /* critical section */
                  j = (i + 1) % n;
                  while ((j != i) && !waiting[j])
                        j = (j + 1) % n;
                  if (j == i)
                        lock = false;
                  else
                        waiting[j] = false;
                  /* remainder section */
             } while (true);
Operating System Concepts – 9th Edition        5.22   Silberschatz, Galvin and Gagne ©2013
                                          Mutex Locks
          Previous solutions are complicated and generally inaccessible
           to application programmers
          OS designers build software tools to solve critical section
           problem
              Simplest is mutex lock
              Protect a critical section by first acquire() a lock then
               release() the lock
                 Boolean variable indicating if lock is available or not
          Calls to acquire() and release() must be atomic
             Usually implemented via hardware atomic instructions
          But this solution requires busy waiting
            This lock therefore called a spinlock
Operating System Concepts – 9th Edition       5.23                   Silberschatz, Galvin and Gagne ©2013
                                 acquire() and release()
                acquire() {
                     while (!available)
                              ; /* busy wait */
                        available = false;;
                  }
                 release() {
                        available = true;
                  }
                 do {
                  acquire lock
                        critical section
                  release lock
                      remainder section
              } while (true);
Operating System Concepts – 9th Edition           5.24   Silberschatz, Galvin and Gagne ©2013
                                          Semaphore
              Synchronization tool that provides more sophisticated ways (than Mutex locks) for
               process to synchronize their activities.
              Semaphore S – integer variable
              Can only be accessed via two indivisible (atomic) operations
               wait() and signal()
                 
                  Originally called P() and V()
            wait(S) {
                         while (S <= 0)
                            ; // busy wait
                         S--;
                 }
              Definition of the signal() operation
                 signal(S) {
                         S++;
                 }
Operating System Concepts – 9th Edition         5.25                      Silberschatz, Galvin and Gagne ©2013
                                          Semaphore Usage
              Counting semaphore – integer value can range over an unrestricted
               domain
              Binary semaphore – integer value can range only between 0 and 1
                     Same as a mutex lock
              Can solve various synchronization problems
              Consider P1 and P2 that require S1 to happen before S2
                Create a semaphore “synch” initialized to 0
                 P1:
                       S 1;
                       signal(synch);
                 P2:
                       wait(synch);
                       S 2;
              Can implement a counting semaphore S as a binary semaphore
Operating System Concepts – 9th Edition          5.26                   Silberschatz, Galvin and Gagne ©2013
                         Semaphore Implementation
               Must guarantee that no two processes can execute the wait()
                and signal() on the same semaphore at the same time
               Thus, the implementation becomes the critical section problem
                where the wait and signal code are placed in the critical
                section
                     Could now have busy waiting in critical section
                      implementation
                           But implementation code is short
                           Little busy waiting if critical section rarely occupied
               Note that applications may spend lots of time in critical sections
                and therefore this is not a good solution
Operating System Concepts – 9th Edition              5.27                     Silberschatz, Galvin and Gagne ©2013
                    Semaphore Implementation with no Busy waiting
Operating System Concepts – 9th Edition            5.28                Silberschatz, Galvin and Gagne ©2013
                         Implementation with no Busy waiting (Cont.)
               wait(semaphore *S) {
                     S->value--;
                     if (S->value < 0) {
                        add this process to S->list;
                          block();
                     }
               }
               signal(semaphore *S) {
                     S->value++;
                     if (S->value <= 0) {
                        remove a process P from S->list;
                          wakeup(P);
                     }
               }
Operating System Concepts – 9th Edition    5.29            Silberschatz, Galvin and Gagne ©2013
                                   Deadlock and Starvation
              Deadlock – two or more processes are waiting indefinitely for an
               event that can be caused by only one of the waiting processes
              Let S and Q be two semaphores initialized to 1
                              P0                   P1
                                    wait(S);                    wait(Q);
                                    wait(Q);                    wait(S);
                        ...                  ...
                                    signal(S);                   signal(Q);
                                    signal(Q);                   signal(S);
Operating System Concepts – 9th Edition            5.30                    Silberschatz, Galvin and Gagne ©2013
                  Classical Problems of Synchronization
              Classical problems used to test newly-proposed synchronization
               schemes
                    Bounded-Buffer Problem
                    Readers and Writers Problem
                    Dining-Philosophers Problem
Operating System Concepts – 9th Edition       5.31                 Silberschatz, Galvin and Gagne ©2013
                                    Bounded-Buffer Problem
Operating System Concepts – 9th Edition     5.32             Silberschatz, Galvin and Gagne ©2013
                       Bounded Buffer Problem (Cont.)
                   do {
                              ...
                               /* produce an item in next_produced */
                              ...
                          wait(empty);
                          wait(mutex);
                                ...
                                /* add next produced to the buffer */
                                ...
                          signal(mutex);
                          signal(full);
                     } while (true);
Operating System Concepts – 9th Edition         5.33               Silberschatz, Galvin and Gagne ©2013
                       Bounded Buffer Problem (Cont.)
              The structure of the consumer process
                  Do {
                         wait(full);
                         wait(mutex);
                            ...
                         /* remove an item from buffer to next_consumed */
                               ...
                         signal(mutex);
                         signal(empty);
                            ...
                         /* consume the item in next consumed */
                         ...
                   } while (true);
Operating System Concepts – 9th Edition        5.34                Silberschatz, Galvin and Gagne ©2013
                                  Readers-Writers Problem
              A data set is shared among a number of concurrent processes
                     Readers – only read the data set; they do not perform any updates
                     Writers – can both read and write
              Problem – allow multiple readers to read at the same time
                     Only one single writer can access the shared data at the same time
              Several variations of how readers and writers are considered – all
               involve some form of priorities
              Shared Data
                     Data set
                     Semaphore rw_mutex initialized to 1
                     Semaphore mutex initialized to 1
                     Integer read_count initialized to 0
Operating System Concepts – 9th Edition        5.35                   Silberschatz, Galvin and Gagne ©2013
                      Readers-Writers Problem (Cont.)
                       do {
                                  wait(rw_mutex);
                                    ...
                                  /* writing is performed */
                                          ...
                             signal(rw_mutex);
                   } while (true);
Operating System Concepts – 9th Edition             5.36       Silberschatz, Galvin and Gagne ©2013
                      Readers-Writers Problem (Cont.)
              The structure of a reader process
                       do {
                                     wait(mutex);
                                     read_count++;
                                     if (read_count == 1)
                                     wait(rw_mutex);
                               signal(mutex);
                                      ...
                                     /* reading is performed */
                                          ...
                               wait(mutex);
                                  read count--;
                                  if (read_count == 0)
                               signal(rw_mutex);
                               signal(mutex);
                       } while (true);
Operating System Concepts – 9th Edition            5.37           Silberschatz, Galvin and Gagne ©2013
                     Readers-Writers Problem Variations
               First variation – no reader kept waiting unless writer has
                permission to use shared object
               Second variation – once writer is ready, it performs the
                write ASAP
               Both may have starvation leading to even more variations
               Problem is solved on some systems by kernel providing
                reader-writer locks
Operating System Concepts – 9th Edition       5.38                    Silberschatz, Galvin and Gagne ©2013
                           Dining-Philosophers Problem
Operating System Concepts – 9th Edition                5.39                    Silberschatz, Galvin and Gagne ©2013
                  Dining-Philosophers Problem Algorithm
              The structure of Philosopher i:
                       do {
                               wait (chopstick[i] );
                                wait (chopstick[ (i + 1) % 5] );
// eat
                                signal (chopstick[i] );
                                signal (chopstick[ (i + 1) % 5] );
// think
                       } while (TRUE);
                 What is the problem with this algorithm?
Operating System Concepts – 9th Edition           5.40               Silberschatz, Galvin and Gagne ©2013
                      Dining-Philosophers Problem Algorithm (Cont.)
               Deadlock handling
                      Allow at most 4 philosophers to be sitting
                      simultaneously at the table.
                      Allow a philosopher to pick up the forks only if both
                      are available (picking must be done in a critical
                      section.
                      Use an asymmetric solution -- an odd-numbered
                      philosopher picks up first the left chopstick and then
                      the right chopstick. Even-numbered philosopher picks
                       up first the right chopstick and then the left chopstick.
Operating System Concepts – 9th Edition          5.41                     Silberschatz, Galvin and Gagne ©2013
                             Problems with Semaphores
Operating System Concepts – 9th Edition         5.42                    Silberschatz, Galvin and Gagne ©2013
                                           Monitors
              A high-level abstraction that provides a convenient and effective
               mechanism for process synchronization
              Abstract data type, internal variables only accessible by code within the
               procedure
              Only one process may be active within the monitor at a time
              But not powerful enough to model some synchronization schemes
                        monitor monitor-name
                        {
                          // shared variable declarations
                          procedure P1 (…) { …. }
Operating System Concepts – 9th Edition           5.43                      Silberschatz, Galvin and Gagne ©2013
                              Schematic view of a Monitor
Operating System Concepts – 9th Edition   5.44      Silberschatz, Galvin and Gagne ©2013
                                          Condition Variables
          condition x, y;
              Two operations are allowed on a condition variable:
                    x.wait() – a process that invokes the operation is
                     suspended until x.signal()
                    x.signal() – resumes one of processes (if any) that
                     invoked x.wait()
                          If no x.wait() on the variable, then it has no effect on
                           the variable
Operating System Concepts – 9th Edition           5.45                  Silberschatz, Galvin and Gagne ©2013
                      Monitor with Condition Variables
Operating System Concepts – 9th Edition   5.46   Silberschatz, Galvin and Gagne ©2013
                             Condition Variables Choices
               If process P invokes x.signal(), and process Q is suspended in
                x.wait(), what should happen next?
                     Both Q and P cannot execute in paralel. If Q is resumed, then P
                      must wait
               Options include
                     Signal and wait – P waits until Q either leaves the monitor or it
                      waits for another condition
                     Signal and continue – Q waits until P either leaves the monitor or it
                      waits for another condition
                     Both have pros and cons – language implementer can decide
                     Monitors implemented in Concurrent Pascal compromise
                           P executing signal immediately leaves the monitor, Q is
                            resumed
                     Implemented in other languages including Mesa, C#, Java
Operating System Concepts – 9th Edition           5.47                   Silberschatz, Galvin and Gagne ©2013
                    Monitor Solution to Dining Philosophers
               monitor DiningPhilosophers
               {
                  enum { THINKING; HUNGRY, EATING) state [5] ;
                  condition self [5];
Operating System Concepts – 9th Edition   5.48               Silberschatz, Galvin and Gagne ©2013
                   Solution to Dining Philosophers (Cont.)
                            initialization_code() {
                               for (int i = 0; i < 5; i++)
                               state[i] = THINKING;
                             }
               }
Operating System Concepts – 9th Edition       5.49           Silberschatz, Galvin and Gagne ©2013
                 Solution to Dining Philosophers (Cont.)
DiningPhilosophers.pickup(i);
EAT
DiningPhilosophers.putdown(i);
Operating System Concepts – 9th Edition             5.50          Silberschatz, Galvin and Gagne ©2013
                  Monitor Implementation Using Semaphores
                  Variables
                                 wait(mutex);
                                      …
                                            body of F;
                                      …
                                 if (next_count > 0)
                                    signal(next)
                                 else
                                    signal(mutex);
Operating System Concepts – 9th Edition        5.51                  Silberschatz, Galvin and Gagne ©2013
                    Monitor Implementation – Condition Variables
                       x_count++;
                       if (next_count > 0)
                          signal(next);
                       else
                          signal(mutex);
                       wait(x_sem);
                       x_count--;
Operating System Concepts – 9th Edition      5.52                Silberschatz, Galvin and Gagne ©2013
                       Monitor Implementation (Cont.)
                      if (x_count > 0) {
                         next_count++;
                         signal(x_sem);
                         wait(next);
                         next_count--;
                      }
Operating System Concepts – 9th Edition    5.53                Silberschatz, Galvin and Gagne ©2013
                    Resuming Processes within a Monitor
Operating System Concepts – 9th Edition         5.54                    Silberschatz, Galvin and Gagne ©2013
                                   Single Resource allocation
                Allocate a single resource among competing processes using
                 priority numbers that specify the maximum time a process
                 plans to use the resource
                                          R.acquire(t);
                                              ...
                                           access the resurce;
                                              ...
R.release;
Operating System Concepts – 9th Edition            5.55           Silberschatz, Galvin and Gagne ©2013
                  A Monitor to Allocate Single Resource
                       monitor ResourceAllocator
                       {
                          boolean busy;
                          condition x;
                          void acquire(int time) {
                               if (busy)
                                   x.wait(time);
                               busy = TRUE;
                          }
                          void release() {
                               busy = FALSE;
                               x.signal();
                          }
                       initialization code() {
                            busy = FALSE;
                          }
                       }
Operating System Concepts – 9th Edition     5.56     Silberschatz, Galvin and Gagne ©2013
                                Synchronization Examples
              Solaris
              Windows
              Linux
              Pthreads
Operating System Concepts – 9th Edition   5.57      Silberschatz, Galvin and Gagne ©2013
                                    Solaris Synchronization
              Implements a variety of locks to support multitasking, multithreading
               (including real-time threads), and multiprocessing
              Uses adaptive mutexes for efficiency when protecting data from short
               code segments
                    Starts as a standard semaphore spin-lock
                    If lock held, and by a thread running on another CPU, spins
                    If lock held by non-run-state thread, block and sleep waiting for signal of
                     lock being released
              Uses condition variables
              Uses readers-writers locks when longer sections of code need
               access to data
              Uses turnstiles to order the list of threads waiting to acquire either an
               adaptive mutex or reader-writer lock
                    Turnstiles are per-lock-holding-thread, not per-object
              Priority-inheritance per-turnstile gives the running thread the highest of
               the priorities of the threads in its turnstile
Operating System Concepts – 9th Edition             5.58                       Silberschatz, Galvin and Gagne ©2013
                                Windows Synchronization
Operating System Concepts – 9th Edition           5.59                    Silberschatz, Galvin and Gagne ©2013
                                     Linux Synchronization
              Linux:
                     Prior to kernel Version 2.6, disables interrupts to
                      implement short critical sections
                     Version 2.6 and later, fully preemptive
              Linux provides:
                     Semaphores
                     atomic integers
                     spinlocks
                     reader-writer versions of both
              On single-cpu system, spinlocks replaced by enabling and
               disabling kernel preemption
Operating System Concepts – 9th Edition           5.60                      Silberschatz, Galvin and Gagne ©2013
                                  Pthreads Synchronization
                Pthreads API is OS-independent
                It provides:
                      mutex locks
                      condition variable
                Non-portable extensions include:
                      read-write locks
                      spinlocks
Operating System Concepts – 9th Edition      5.61     Silberschatz, Galvin and Gagne ©2013
                                      Alternative Approaches
                Transactional Memory
 OpenMP
Operating System Concepts – 9th Edition       5.62       Silberschatz, Galvin and Gagne ©2013
                                          Transactional Memory
                A memory transaction is a sequence of read-write operations
                 to memory that are performed atomically.
                                          void update()
                                  {
                                        /* read/write memory */
                                    }
Operating System Concepts – 9th Edition            5.63           Silberschatz, Galvin and Gagne ©2013
                                                   OpenMP
                OpenMP is a set of compiler directives and API that support
                 parallel progamming.
Operating System Concepts – 9th Edition            5.64              Silberschatz, Galvin and Gagne ©2013
                    Functional Programming Languages
Operating System Concepts – 9th Edition       5.65                   Silberschatz, Galvin and Gagne ©2013
                                    End of Chapter 5
Operating System Concepts – 9th Edition Silberschatz, Galvin and Gagne ©2013