Module 7: Process Synchronization

Download Report

Transcript Module 7: Process Synchronization

Chapter 6: Synchronization
Module 6: Synchronization
 6.1 Background
 6.2 The Critical-Section Problem
 6.3 Peterson’s Solution
 6.4 Synchronization Hardware
 6.5 Semaphores
 6.6 Classic Problems of Synchronization
 6.7 Monitors
 6.8 Synchronization Examples
 6.9 Atomic Transactions
Operating System Principles
6.2
Silberschatz, Galvin and Gagne ©2005
Review 3.4.1 Interproces Communication
 Independent process cannot affect or be affected
by the execution of another process
 Cooperating process can affect or be affected by
the execution of another process
 Advantages of process cooperation

Information sharing

Computation speed-up

Modularity

Convenience
Operating System Principles
6.3
Silberschatz, Galvin and Gagne ©2005
Communications Models
Shared memory
Message passing
Operating System Principles
6.4
Silberschatz, Galvin and Gagne ©2005
Producer-Consumer Problem
 Paradigm for cooperating processes, producer
process produces information that is consumed by a
consumer process


unbounded-buffer places no practical limit on the size of the
buffer
bounded-buffer assumes that there is a fixed buffer size
 Shared-Memory Solution : Shared data
#define BUFFER_SIZE 10
Typedef struct {
...
} item;
item buffer[BUFFER_SIZE];
int in = 0;
int out = 0;
Operating System Principles
6.5
Silberschatz, Galvin and Gagne ©2005
Bounded-Buffer – Producer() Method
while (true) {
/* produce an item in nextProduced*/
while (( (in + 1) % BUFFER_SIZE) == out)
; /* do nothing -- no free buffers */
buffer[in] = nextProduced;
in = (in + 1) % BUFFER_SIZE;
Solution is correct,
}
Bounded-Buffer – Consumer() Method
while (true) {
but can only use
BUFFER_SIZE-1 elements
while (in == out)
; // do nothing -- nothing to consume
nextConsumed = buffer[out];
out = (out + 1) % BUFFER SIZE;
/* consume the item in nextConsumed */;
}
Operating System Principles
6.6
Silberschatz, Galvin and Gagne ©2005
BUFFER_SIZE solution
One more shared memory variable: counter
Operating System Principles
6.7
Silberschatz, Galvin and Gagne ©2005
Still Have Problems
Operating System Principles
6.8
Silberschatz, Galvin and Gagne ©2005
6.1 Background
 Concurrent access to shared data may result in
data inconsistency
 Maintaining data consistency requires mechanisms
to ensure the orderly execution of cooperating
processes
 Suppose that we wanted to provide a solution to the
consumer-producer problem (Section 3.4.1) that fills
all the buffers. We can do so by having an integer
count that keeps track of the number of full buffers.
Initially, count 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 Principles
6.9
Silberschatz, Galvin and Gagne ©2005
while (true) {
/* produce an item and put in nextProduced */
while (counter == BUFFER_SIZE)
Producer
; // do nothing
buffer [in] = nextProduced;
in = (in + 1) % BUFFER_SIZE;
counter++;
}
while (true) {
while (counter == 0)
Consumer
; // do nothing
nextConsumed = buffer[out];
out = (out + 1) % BUFFER_SIZE;
counter--;
/* consume the item in nextConsumed
}
Operating System Principles
6.10
Silberschatz, Galvin and Gagne ©2005
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
Operating System Principles
6.11
Silberschatz, Galvin and Gagne ©2005
Race Condition
 Consider this execution interleaving with “counter = 5”
initially:
T0: producer execute register1 = counter {register1 = 5}
T1: producer execute register1 = register1 + 1 {register1 = 6}
T2: consumer execute register2 = counter {register2 = 5}
T3: consumer execute register2 = register2 - 1 {register2 = 4}
T4: producer execute counter = register1 {count = 6 }
T5: consumer execute counter = register2 {count = 4}
If the order T4 and T5 is reversed, then the final state is count = 6
Operating System Principles
6.12
Silberschatz, Galvin and Gagne ©2005
6.2 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 some
processes wish to enter their critical sections, then only those
processes that are not executing in their remainder sections can
participate in the decision on which will enter its critical section next,
and this selection 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 Principles
6.13
Silberschatz, Galvin and Gagne ©2005
6.2 Solution to Critical-Section Problem
 Example kernel data structure that is subject to race conditions:

List of open files in the OS

Data structure for free/allocated memory

Process lists

Data structure for interrupts handling
 Approaches in handling critical sections in OS:

Preemptive kernels

Nonpreemptive kernels
 A preemptive kernel is more suitable for real-time programming,
more responsive
訂正: p190 倒數第 3 列第 2 個字
應為 preemptive
Operating System Principles
6.14
Silberschatz, Galvin and Gagne ©2005
6.3 Peterson’s Solution
 Two process solution
 Assume that the LOAD and STORE instructions are atomic; that
is, cannot be interrupted.
 The two processes share two variables:


int turn;
boolean flag[2];
 The variable turn indicates whose turn it is to enter the critical
section.
 The flag array is used to indicate if a process is ready to enter the
critical section. flag[i] = true implies that process Pi is ready!
Operating System Principles
6.15
Silberschatz, Galvin and Gagne ©2005
Algorithm for Process Pi
while (true) {
flag[i] = TRUE;
turn = j;
// j is i -1
while ( flag[j] && turn == j);
entry section
(acquire lock)
CRITICAL SECTION
exit section
(release lock)
flag[i] = FALSE;
REMAINDER SECTION
}
Operating System Principles
6.16
Silberschatz, Galvin and Gagne ©2005
 To prove Peterson’s solution is correct:

Mutual exclusion is preserved

The progress requirement is satisfied

The bounded-waiting requirement is met
Operating System Principles
6.17
Silberschatz, Galvin and Gagne ©2005
6.4 Synchronization Hardware
 Many systems provide hardware support for critical
section code
 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-interruptable
Either test memory word and set value
Or swap contents of two memory words
Operating System Principles
6.18
Silberschatz, Galvin and Gagne ©2005
TestAndndSet Instruction
 Shared boolean variable lock
initialized to false.
 Solution using TestandSet:
 Definition:
while (true) {
while ( TestAndSet (&lock ))
; // do nothing
boolean TestAndSet (boolean *target)
{
boolean rv = *target;
*target = TRUE;
return rv:
// critical section
}
lock = FALSE;
//
remainder section
}
Operating System Principles
6.19
Silberschatz, Galvin and Gagne ©2005
Swap Instruction
 Shared boolean variable lock initialized to
 Definition:
void Swap (boolean *a, boolean *b)
{
boolean temp = *a;
*a = *b;
*b = temp:
}
FALSE; Each process has a local boolean
variable key.
 Solution using Swap:
while (true) {
key = TRUE;
while ( key == TRUE)
Swap (&lock, &key );
//
critical section
lock = FALSE;
//
Does not satisfy
bounded-waiting
Operating System Principles
remainder section
}
6.20
Silberschatz, Galvin and Gagne ©2005
 Common data structure: boolean waiting[n] and boolean lock;
 Solution using TestandSet:
while (true) {
waiting[i] = TRUE;
key = TRUE;
while ( waiting[i] && key)
key = TestAndSet(&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
Bounded-waiting
mutual exclusion
with TestAndSet()
}
Operating System Principles
6.21
Silberschatz, Galvin and Gagne ©2005