Outline Please turn in Homework #2 • Announcements

advertisement
Outline
• Announcements
• Basic Synchronization Principles – continued
– Semaphores
– Bounded-buffer problem
– Read-writer’s problem
Please turn in Homework #2
Announcements
• The second quiz will be at the end of class on
this Thursday – October 9, 2003
– It will be closed-book and closed-note
– It will cover the materials until today with
emphasis on scheduling
– It requires to compute average wait time and
turnaround time (or something like that) and you
need a calculator
5/29/2016
COP4610
2
Announcements – cont.
• Demonstration of Lab 1
– You can sign up to demonstrate your program
tomorrow during the recitation session
– During the demo, Mr. Chen will ask you
questions besides demonstration
5/29/2016
COP4610
3
Comments on Scheduling Algorithms
Process Arrival Time Burst Time
P1
0.0
7
P2
2.0
4
P3
4.0
1
P4
5.0
4
• Wait time and turnaround time
• Round robin
– Where should we place the newly arrived ones?
5/29/2016
COP4610
4
Interacting Processes - review
• Independent process
– Cannot affect or be affected by the other
processes in the system
– Does not share any data with other processes
• Interacting process
– Can affect or be affected by the other processes
– Shares data with other processes
– We focus on interacting processes through
physically or logically shared memory
5/29/2016
COP4610
5
Bounded-Buffer – review
5/29/2016
COP4610
6
Bounded-Buffer - cont.
• Suppose we have one producer and one
consumer, the variable counter is 5
– Producer: counter = counter +1
P1: load counter, r1
P2: add r1, #1, r2
P3: store r2, counter
– Consumer: counter = counter - 1
C1: load counter, r1
C2: add r1, #-1, r2
C3: store r2, counter
5/29/2016
COP4610
7
Bounded-Buffer - cont.
• A particular execution sequence
– P1: load counter, r1
– P2: add r1, #1, r2
--- Context switch ---– C1: load counter, r1
– C2: add r1, #-1, r2
– C3: store r2, counter
--- Context switch ---– P3: store r2, counter
– What is the value of counter?
5/29/2016
COP4610
8
Bounded-Buffer - cont.
• A particular execution sequence
– C1: load counter, r1
– C2: add r1, #-1, r2
--- Context switch ---– P1: load counter, r1
– P2: add r1, #1, r2
– P3: store r2, counter
--- Context switch ---– C3: store r2, counter
– What is the value of counter this time?
5/29/2016
COP4610
9
Bounded-Buffer - cont.
• A particular execution sequence
– C1: load counter, r1
– C2: add r1, #-1, r2
– C3: store r2, counter
--- Context switch ---– P1: load counter, r1
– P2: add r1, #1, r2
– P3: store r2, counter
--- Context switch ---– What is the value of counter this time?
5/29/2016
COP4610
10
Race Condition
• Race condition
– When several processes access and manipulate
the same data concurrently, there is a race among
the processes
– The outcome of the execution depends on the
particular order in which the access takes place
– This is called a race condition
5/29/2016
COP4610
11
Traffic Intersections
5/29/2016
COP4610
12
A Semaphore
5/29/2016
COP4610
13
The Critical-Section Problem
• n processes all competing to use some shared
data
• Each process has code segments, called
critical section, in which the shared data is
accessed.
• Problem – ensure that when one process is
executing in its critical section, no other
process is allowed to execute in its critical
section, called mutual exclusion
5/29/2016
COP4610
14
The Critical-Section Problem – cont.
• Structure of process Pi
repeat
entry section
critical section
exit section
reminder section
until false;
5/29/2016
COP4610
15
Requirements for Critical-Section Solutions
• Mutual Exclusion.
– If process Pi is executing in its critical section, then no
other processes can be executing in their critical sections.
• 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.
• 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.
5/29/2016
COP4610
16
Solution through Disabling Interrupts
• In a uni-processor system, an interrupt causes
the race condition
– The scheduler can be called in the interrupt
handler, resulting in context switch and data
inconsistency
5/29/2016
COP4610
17
Solution through Disabling Interrupts – cont.
• Process Pi
repeat
disableInterrupts(); //entry section
critical section
enableInterrupts(); //exit section
reminder section
until false;
5/29/2016
COP4610
18
Solution through Disabling Interrupts – cont.
5/29/2016
COP4610
19
Solution through Disabling Interrupts – cont.
• This solution may affect the behavior of the I/O
system
– Interrupts can be disabled for an arbitrarily long time
• The interrupts can be disabled permanently if the program
contains an infinite loop in its critical section
– User programs are not allowed to enable and disable
interrupts directly
• However, if the operating system can provide system calls,
a user can use the system calls for synchronization
– Called semaphores and related system calls
5/29/2016
COP4610
20
Software Attempt to Solve the Problem
• Only 2 processes, P1 and P2
• General structure of process Pi (other process Pj)
repeat
entry section
critical section
exit section
reminder section
until false;
• Processes may share some common variables to
synchronize their actions.
5/29/2016
COP4610
21
Algorithm 1
• Shared variables:
– var turn: (0..1);
initially turn = 0
– turn - i  Pi can enter its critical section
• Process Pi
repeat
while turn  i do no-op;
critical section
turn := j;
reminder section
until false;
• Satisfies mutual exclusion, but not progress
5/29/2016
COP4610
22
Algorithm 2
• Shared variables
– var flag: array [0..1] of boolean;
initially flag [0] = flag [1] = false.
– flag [i] = true  Pi ready to enter its critical section
• Process Pi
repeat
flag[i] := true;
while flag[j] do no-op;
critical section
flag [i] := false;
remainder section
until false;
• Satisfies mutual exclusion, but not progress requirement.
5/29/2016
COP4610
23
Algorithm 2 – version 1
• Shared variables
– var flag: array [0..1] of boolean;
initially flag [0] = flag [1] = false.
– flag [i] = true  Pi ready to enter its critical section
• Process Pi
repeat
while flag[j] do no-op;
flag[i] := true;
critical section
flag [i] := false;
remainder section
until false;
• Does not satisfy mutual exclusion
5/29/2016
COP4610
24
Algorithm 3
• Combined shared variables of algorithms 1 and 2.
• Process Pi
repeat
flag [i] := true;
turn := j;
while (flag [j] and turn = j) do no-op;
critical section
flag [i] := false;
remainder section
until false;
• Meets all three requirements; solves the critical-section problem
for two processes.
5/29/2016
COP4610
25
Bakery Algorithm
Critical section for n processes
• Before entering its critical section, process receives
a number. Holder of the smallest number enters the
critical section.
• If processes Pi and Pj receive the same number, if i
< j, then Pi is served first; else Pj is served first.
• The numbering scheme always generates numbers
in increasing order of enumeration; i.e.,
1,2,3,3,3,3,4,5...
5/29/2016
COP4610
26
Bakery Algorithm – cont.
• Notation < lexicographical order (ticket #, process
id #)
– (a,b) < c,d) if a < c or if a = c and b < d
– max (a0,…, an-1) is a number, k, such that k  ai for i - 0,
…, n – 1
• Shared data
var choosing: array [0..n – 1] of boolean;
number: array [0..n – 1] of integer,
Data structures are initialized to false and 0
respectively
5/29/2016
COP4610
27
Bakery Algorithm (Cont.)
repeat
choosing[i] := true;
number[i] := max(number[0], number[1], …, number [n – 1])+1;
choosing[i] := false;
for j := 0 to n – 1
do begin
while choosing[j] do no-op;
while number[j]  0
and (number[j],j) < (number[i], i) do no-op;
end;
critical section
number[i] := 0;
remainder section
until false;
5/29/2016
COP4610
28
Algorithm 4
• Shared variables:
– boolean lock;
initially lock = FALSE
– lock is FALSE  Pi can enter its critical section
• Process P1
Process P2
repeat
while (lock) do no-op;
lock = TRUE;
critical section
lock = FALSE;
reminder section
until false;
repeat
while (lock) do no-op;
lock = TRUE;
critical section
lock = FALSE
reminder section
until false;
5/29/2016
COP4610
29
Busy Wait Condition
shared boolean lock = FALSE;
shared double balance;
Code for p1
Code for p2
COP4610
Interrupt
lock = FALSE
Interrupt
Interrupt
5/29/2016
lock = TRUE
p2
p1
/* Acquire the lock */
while(lock) ;
lock = TRUE;
/* Execute critical sect */
balance = balance - amount;
/* Release lock */
lock = FALSE;
Blocked
at while
/* Acquire the lock */
while(lock) ;
lock = TRUE;
/* Execute critical sect */
balance = balance + amount;
/* Release lock */
lock = FALSE;
30
Synchronization Hardware
• Test and modify the content of a word atomically
(indivisibly)
– The procedure cannot be interrupted until it has completed the
routine
– Implemented as a test-and-set instruction
boolean Test-and-Set (boolean target)
{ boolean tmp
tmp = target;
target = true;
return tmp;
}
5/29/2016
COP4610
31
Test and Set Instruction – cont.
• TS(m): [Reg_i = memory[m]; memory[m] = TRUE;]
Data
CC
Register Register
R3
…
m
Data
CC
Register Register
…
R3
m
FALSE
Primary
Memory
(a) Before Executing TS
5/29/2016
FALSE
=0
TRUE
Primary
Memory
(b) After Executing TS
COP4610
32
Mutual Exclusion with Test-and-Set
• Shared data: boolean lock ;
– Initially false
• Process Pi
repeat
while Test-and-Set (lock) do no-op;
critical section
lock = false;
remainder section
until false;
5/29/2016
COP4610
33
Semaphores
• Semaphore S – integer variable
• can only be accessed via two indivisible
(atomic) operations
– As if they were a single machine instruction
wait (S): while S 0 do no-op;
S := S – 1;
signal (S): S := S + 1;
5/29/2016
COP4610
34
Two Types of Semaphores
• Counting semaphore – integer value can
range over an unrestricted domain.
• Binary semaphore – integer value can
range only between 0 and 1
– Can be simpler to implement.
• Can implement a counting semaphore S
using binary semaphores.
5/29/2016
COP4610
35
Example: Critical Section of n Processes
• Shared variables
– var mutex : semaphore
– initially mutex = 1
• Process Pi
repeat
wait(mutex);
critical section
signal(mutex);
remainder section
until false;
5/29/2016
COP4610
36
Shared Account Balance Problem
Proc_0() {
. . .
/* Enter the CS */
P(mutex);
balance += amount;
V(mutex);
. . .
}
proc_1() {
. . .
/* Enter the CS */
P(mutex);
balance -= amount;
V(mutex);
. . .
}
semaphore mutex = 1;
fork(proc_0, 0);
fork(proc_1, 0);
5/29/2016
COP4610
37
Sharing Two Variables
proc_A() {
while(TRUE) {
<compute section A1>;
update(x);
/* Signal proc_B */
V(s1);
<compute section A2>;
/* Wait for proc_B */
P(s2);
retrieve(y);
}
}
proc_B() {
while(TRUE) {
/* Wait for proc_A */
P(s1);
retrieve(x);
<compute section B1>;
update(y);
/* Signal proc_A */
V(s2);
<compute section B2>;
}
}
semaphore s1 = 0;
semaphore s2 = 0;
fork(proc_A, 0);
fork(proc_B, 0);
5/29/2016
COP4610
38
Bounded Buffer Problem
Empty Pool
Producer
Consumer
Full Pool
5/29/2016
COP4610
39
Bounded Buffer Problem – cont.
producer() {
consumer() {
buf_type *next, *here;
buf_type *next, *here;
while(TRUE) {
while(TRUE) {
produce_item(next);
/* Claim full buffer */
/* Claim an empty */
P(full);
P(empty);
P(mutex);
P(mutex);
here = obtain(full);
here = obtain(empty);
V(mutex);
V(mutex);
copy_buffer(here, next);
copy_buffer(next, here);
P(mutex);
P(mutex);
release(here, emptyPool);
release(here, fullPool);
V(mutex);
V(mutex);
/* Signal an empty buffer */
/* Signal a full buffer */
V(empty);
V(full);
consume_item(next);
}
}
}
}
semaphore mutex = 1;
semaphore full = 0;
/* A general (counting) semaphore */
semaphore empty = N;
/* A general (counting) semaphore */
buf_type buffer[N];
fork(producer, 0);
fork(consumer, 0);
5/29/2016
COP4610
40
Bounded Buffer Problem – cont.
producer() {
consumer() {
buf_type *next, *here;
buf_type *next, *here;
while(TRUE) {
while(TRUE) {
produce_item(next);
/* Claim full buffer */
/* Claim an empty */
P(full);
P(empty);
P(mutex);
P(mutex);
here = obtain(full);
here = obtain(empty);
V(mutex);
V(mutex);
copy_buffer(here, next);
copy_buffer(next, here);
P(mutex);
P(mutex);
release(here, emptyPool);
release(here, fullPool);
V(mutex);
V(mutex);
/* Signal an empty buffer */
/* Signal a full buffer */
V(empty);
V(full);
consume_item(next);
}
}
}
}
semaphore mutex = 1;
semaphore full = 0;
/* A general (counting) semaphore */
semaphore empty = N;
/* A general (counting) semaphore */
buf_type buffer[N];
fork(producer, 0);
fork(consumer, 0);
5/29/2016
COP4610
41
Bounded Buffer Problem – cont.
consumer() {
producer() {
buf_type *next, *here;
buf_type *next, *here;
while(TRUE) {
while(TRUE) {
/* Claim full buffer */
produce_item(next);
P(mutex);
/* Claim an empty */
P(full);
P(empty);
here = obtain(full);
P(mutex);
V(mutex);
here = obtain(empty);
copy_buffer(here, next);
V(mutex);
P(mutex);
copy_buffer(next, here);
release(here, emptyPool);
P(mutex);
V(mutex);
release(here, fullPool);
/* Signal an empty buffer */
V(mutex);
V(empty);
/* Signal a full buffer */
consume_item(next);
V(full);
}
}
}
}
semaphore mutex = 1;
semaphore full = 0;
/* A general (counting) semaphore */
semaphore empty = N;
/* A general (counting) semaphore */
buf_type buffer[N];
fork(producer, 0);
fork(consumer, 0);
5/29/2016
COP4610
42
Readers-Writers Problem
Writers
Readers
5/29/2016
COP4610
43
Readers-Writers Problem (2)
Writer
Writer
Writer
Writer
Writer
Writer
Writer
Reader
Reader
Reader
Reader
Reader
Reader
Reader
Reader
Shared Resource
5/29/2016
COP4610
44
Readers-Writers Problem (3)
Writer
Writer
Writer
Writer
Writer
Writer
Writer
Reader
Reader
Reader
Reader
Reader
Reader
Reader
Reader
Shared Resource
5/29/2016
COP4610
45
Readers-Writers Problem (4)
Reader
Reader
Reader
Reader
Reader
Reader
Reader
Reader
Writer
Writer
Writer
Writer
Writer
Writer
Writer
Shared Resource
5/29/2016
COP4610
46
Readers-writers with active readers
5/29/2016
COP4610
47
First and Second Policy
5/29/2016
COP4610
48
First Solution
reader() {
writer() {
while(TRUE) {
while(TRUE) {
<other computing>;
<other computing>;
P(mutex);
P(writeBlock);
readCount++;
/* Critical section */
if(readCount == 1)
access(resource);
P(writeBlock);
V(writeBlock);
V(mutex);
}
/* Critical section */
}
access(resource);
P(mutex);
readCount--;
•First reader competes with writers
if(readCount == 0)
V(writeBlock);
•Last reader signals writers
V(mutex);
}
}
resourceType *resource;
int readCount = 0;
semaphore mutex = 1;
semaphore writeBlock = 1;
fork(reader, 0);
fork(writer, 0);
5/29/2016
COP4610
49
First Solution (2)
reader() {
while(TRUE) {
<other computing>;
P(mutex);
readCount++;
if(readCount == 1)
P(writeBlock);
V(mutex);
/* Critical section */
access(resource);
P(mutex);
readCount--;
if(readCount == 0)
V(writeBlock);
V(mutex);
}
}
resourceType *resource;
int readCount = 0;
semaphore mutex = 1;
semaphore writeBlock = 1;
fork(reader, 0);
fork(writer, 0);
5/29/2016
writer() {
while(TRUE) {
<other computing>;
P(writeBlock);
/* Critical section */
access(resource);
V(writeBlock);
}
}
•First reader competes with writers
•Last reader signals writers
•Any writer must wait for all readers
•Readers can starve writers
•“Updates” can be delayed forever
•May not be what we want
COP4610
50
Writer Precedence
reader() {
while(TRUE) {
<other computing>;
P(readBlock);
P(mutex1);
readCount++;
if(readCount == 1)
P(writeBlock);
V(mutex1);
V(readBlock);
4
2
1
access(resource);
P(mutex1);
readCount--;
if(readCount == 0)
V(writeBlock);
V(mutex1);
writer() {
while(TRUE) {
<other computing>;
P(mutex2);
writeCount++;
if(writeCount == 1)
P(readBlock);
3
V(mutex2);
P(writeBlock);
access(resource);
V(writeBlock);
P(mutex2)
writeCount--;
if(writeCount == 0)
V(readBlock);
V(mutex2);
}
}
}
}
int readCount = 0, writeCount = 0;
semaphore mutex = 1, mutex2 = 1;
semaphore readBlock = 1, writeBlock = 1, writePending = 1;
fork(reader, 0);
5/29/2016
COP4610
51
fork(writer, 0);
Writer Precedence (2)
reader() {
writer() {
while(TRUE) {
while(TRUE) {
<other computing>;
<other computing>;
P(mutex2);
4 P(writePending);
P(readBlock);
writeCount++;
P(mutex1);
if(writeCount == 1)
readCount++;
P(readBlock);
3
if(readCount == 1)
V(mutex2);
2
P(writeBlock);
P(writeBlock);
V(mutex1);
access(resource);
V(readBlock);
V(writeBlock);
1 V(writePending);
P(mutex2)
access(resource);
writeCount--;
P(mutex1);
if(writeCount == 0)
readCount--;
V(readBlock);
if(readCount == 0)
V(mutex2);
V(writeBlock);
}
V(mutex1);
}
}
}
int readCount = 0, writeCount = 0;
semaphore mutex = 1, mutex2 = 1;
semaphore readBlock = 1, writeBlock = 1, writePending = 1;
fork(reader, 0);
5/29/2016
COP4610
52
fork(writer, 0);
The Sleepy Barber
• Barber can cut one person’s hair at a time
• Other customers wait in a waiting room
Entrance to Waiting
Room (sliding door)
Shop Exit
Entrance to Barber’s
Room (sliding door)
Waiting Room
5/29/2016
COP4610
53
Sleepy Barber
customer() {
while(TRUE) {
customer = nextCustomer();
if(emptyChairs == 0)
continue;
P(chair);
P(mutex);
emptyChairs--;
takeChair(customer);
V(mutex);
V(waitingCustomer);
}
}
barber() {
while(TRUE) {
P(waitingCustomer);
P(mutex);
emptyChairs++;
takeCustomer();
V(mutex);
V(chair);
}
}
semaphore mutex = 1, chair = N, waitingCustomer = 0;
int emptyChairs = N;
fork(customer, 0);
fork(barber, 0);
5/29/2016
COP4610
54
Implementing Semaphores
• Minimize effect on the I/O system
• Processes are only blocked on their own
critical sections (not critical sections that they
should not care about)
• If disabling interrupts, be sure to bound the
time they are disabled
5/29/2016
COP4610
55
Implementing Semaphores Using Interrupts
class semaphore {
int value;
public:
semaphore(int v = 1) { value = v;};
P(){
disableInterrupts();
while(value == 0) {
enableInterrupts();
disableInterrupts();
}
value--;
enableInterrupts();
};
V(){
disableInterrupts();
value++;
enableInterrupts();
};
};
5/29/2016
COP4610
56
Using the TS Instruction
boolean s = FALSE;
. . .
while(TS(s)) ;
<critical section>
s = FALSE;
. . .
5/29/2016
semaphore s = 1;
. . .
P(s) ;
<critical section>
V(s);
. . .
COP4610
57
Implementing the General Semaphore
struct semaphore {
int value = <initial value>;
boolean mutex = FALSE;
boolean hold = TRUE;
};
shared struct semaphore s;
P(struct semaphore s) {
while(TS(s.mutex)) ;
s.value--;
if(s.value < 0) (
s.mutex = FALSE;
while(TS(s.hold)) ;
}
else
s.mutex = FALSE;
}
5/29/2016
V(struct semaphore s) {
while(TS(s.mutex)) ;
s.value++;
if(s.value <= 0) (
while(!s.hold) ;
s.hold = FALSE;
}
s.mutex = FALSE;
}
COP4610
58
Semaphore Implementation – cont.
• Semaphores implemented using interrupt
disabling and test-and-set require busy
waiting
– This type of semaphores is often called spinlock
5/29/2016
COP4610
59
Semaphore Implementation – cont.
• Define a semaphore as a structure
typedef struct {
int value;
queue L;
} semaphore;
• Assume two simple operations:
– block suspends the process that invokes it.
– wakeup(P) resumes the execution of a blocked
process P.
5/29/2016
COP4610
60
Semaphore Implementation - cont.
• Semaphore operations now defined as
P(S): S.value = S.value – 1;
if S.value < 0
then begin
add this process to S.L;
block;
end;
5/29/2016
COP4610
61
Semaphore Implementation - cont.
V(S):
S.value = S.value + 1;
if S.value  0
then begin
remove a process P from S.L;
wakeup(P);
end;
5/29/2016
COP4610
62
Semaphore Implementation - cont.
• Semaphores are resources in the above
implementation
5/29/2016
COP4610
63
Issues Using Semaphores
• 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
P(S);
P(Q);

V(S);
V(Q)
P1
P(Q);
P(S);

V(Q);
V(S);
• Starvation – indefinite blocking
– A process may never be removed from the semaphore queue
in which it is suspended.
5/29/2016
COP4610
64
Active vs. Passive Semaphores
• A process can dominate the semaphore
– Performs V operation, but continues to execute
– Performs another P operation before releasing the
CPU
– Called a passive implementation of V
• Active implementation calls scheduler as part
of the V operation.
– Changes semantics of semaphore!
– Cause people to rethink solutions
5/29/2016
COP4610
65
Summary
• Processes that share data need to be
synchronized
– Otherwise, a race condition may exist
• Semaphores are the basic mechanism
underlying synchronization and can be used
to solve different synchronization problems
– Critical section problem
– Bounded-buffer problem
– Readers-writers problem
5/29/2016
COP4610
66
Download