Title: Background
1Background
- Shared-memory solution to bounded-buffer problem
allows at most n 1 items in buffer at the same
time. - A solution, where all N buffers are used is not
simple. - Suppose that we modify the producer-consumer code
by adding a variable counter, initialized to 0
and incremented each time a new item is added to
the buffer - Shared data
- define BUFFER_SIZE 10
- typedef struct
- . . .
- item
- item bufferBUFFER_SIZE
- int in 0
- int out 0
- int counter 0
2Bounded-Buffer Attempt
- Producer process
- while (1)
- while (counter BUFFER_SIZE)
- / do nothing /
- bufferin nextProduced
- in (in 1) BUFFER_SIZE
- counter
-
- Consumer process
- while (1)
- while (counter 0)
- / do nothing /
- nextConsumed bufferout
- out (out 1) BUFFER_SIZE
- counter--
3Bounded Buffer
- The statement counter may be implemented in
machine language as - register1 counter
- register1 register1 1counter register1
- The statement counter-- may be implemented
asregister2 counterregister2 register2
1counter register2 - If both the producer and consumer attempt to
update the counter concurrently, the assembly
language statements may get interleaved.
4Bounded Buffer
- Assume counter is initially 5. One interleaving
of statements is - producer register1 counter (register1
5)producer register1 register1 1
(register1 6)consumer register2 counter
(register2 5)consumer register2 register2
1 (register2 4)producer counter
register1 (counter 6)consumer counter
register2 (counter 4) - The value of counter may be either 4 or 6, where
the correct result should be 5. - Interleaving depends upon how the producer and
consumer processes are scheduled. - The statements counter and counter-- must be
performed atomically. - Atomic operation means an operation that
completes in its entirety without interruption.
5Race Condition
- Concurrent access to shared data may result in
data inconsistency. - Race condition The situation where several
processes access and manipulate shared data
concurrently. The final value of the shared data
depends upon which process finishes last. - To prevent race conditions, concurrent processes
must be synchronized. - The concurrent processes have critical sections,
in which they modify shared data - A limited number of processes can be in their
critical sections at the same time.
6The Critical-Section Problem
- N processes all competing to use some shared data
- Each process has a code segment, called critical
section, in which the shared data is accessed. - Problem ensure that maximally R (often R 1)
processes executing in their critical section. - General structure of process Pi
- do
- entry section
- critical section
- exit section
- remainder section
- while (1)
7Solution to Critical Section Problem
- Requirements
- Mutual Exclusion - Maximally R processes in their
critical section - Progress - If less than R processes are in their
critical sections, then a process that wishes to
enter it critical section is not delayed
indefinitely. - Bounded Waiting - Only a bounded amount of
overtaking into critical sections is permitted. - Assumptions
- Assume that each process executes at a non-zero
speed - No assumption concerning relative speed of the
processes. - Atomic execution of machine code instructions
(think of the fetch-interrupt?-decode-execute
cycle) - Types of solutions
- Software - no hardware support but slow
- Hardware supported
82 Processes, 1 at-a-time, Algorithm 1
- Processes P0 and P1
- Shared variables
- int turn 0
- turn i ? Pi can enter its critical section
- Process Pi
- do
- while (turn ! i)
-
- critical section
- turn 1 - i
- reminder section
- while (1)
- Satisfies mutual exclusion, but not progress
- A process can be stuck in its remainder
- Problem is forced alternation
92 Processes, 1 at-a-time, Algorithm 2
- Shared variables
- boolean flag2 false,false
- flagi true ? Pi ready to enter its critical
section - Process Pi
- do
- flagi true
- while (flag1-i)
-
- critical section
- flagi false
- remainder section
- while (1)
- Satisfies mutual exclusion, but not progress
- Both can set flagi before proceeding
- Switching the first two lines violates mutual
exclusion
102 Processes, 1 at-a-time, Algorithm 3(Petersons
Algorithm)
- Combined shared variables of algorithms 1 and 2.
- Process Pi
- do
- flagi true //----Im ready
- turn 1-i //----Its your turn (last
RAM access) - while (flag1-i and turn 1-i)
- //----Wait if other is ready and its
its turn - critical section
- flagi false //----Im not ready any
more - remainder section
- while (1)
- Meets all three requirements solves the
critical-section problem for two processes.
11N Processes, 1 at-a-time, Bakery Algorithm
- 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 lt j, then Pi is served first else Pj is
served first. - Numbers are handed out in non-decreasing order,
e.g., 1,2,3,3,3,3,4,5... - Notation lt? lexicographical order (ticket ,
process id ) - (a,b) lt (c,d) if a lt c or if a c and b lt d
12Bakery Algorithm
- Shared data
- boolean choosingn false
- int numbern 0
- Algorithm for Pi
- do
- choosingi true
- numberi max(number0,number1,,numbern
1)1 - choosingi false
- for (j0 jltn j)
- while (choosingj)
- //---Wait for a process that is
getting a number - while (numberj ! 0 (numberj,j) lt
(numberi,i)) - //---Wait for process with better
numbers -
- critical section
- numberi 0 //---Release the number and
interest - remainder section
- while (1)
13Hardware Supported Solutions
- Turn off interrupts
- Affects multi-tasking - too dangerous
- Affects clock
- Affects critical OS activities
- Atomically swap two variables.
- void Swap(boolean a, boolean b)
- boolean temp a
- a b
- b temp
-
- Test and modify the content of a word atomically
- boolean TestAndSet(boolean target)
- boolean return_value target
- target true
- return(return_value)
14N Processes, 1 at-a-time, Using swap
- Shared data
- boolean lock false //----Nobody using
- Local data
- boolean key
- Process Pi
- do
- key true //---I want in
- while (key) //---Wait until free
- Swap(lock,key)
- critical section
- lock false //---Set it free
- remainder section
-
- Does not satisfy bounded wait
15N Processes, 1 at-a-time, Using TS
- Shared data boolean lock false
- Process Pi
- do
- while (TestAndSet(lock))
-
- critical section
- lock false
- remainder section
-
- Does not satisfy bounded wait
16N Processes, 1 at-a-time, Using TS
- Shared data
- boolean waiting0..n-1 false
- boolean lock false
- Algorithm for Pi
- while (1)
- waitingi true //---I want in
- key true //---Assume another is in C.S.
- while (waitingi key)
- key TestAndSet(lock) //---Busy wait
- waitingi false
- critical section
- j (i1) n //---Look to see whos
waiting - while (j ! i !waitingj)
- j (j1) n
- if (j i) then
- lock false //----No one
- else waitingj false //---Someone
- remainder section
- (see Geoffs example)
17Semaphores
- Working towards a synchronization tool that does
not require busy waiting. - Semaphore S integer variable
- Can only be accessed via two atomic operations
- wait(S) //---P(S)
- when S gt 0 do
- S--
- signal(S) //----V(S)
- S
18N Processes, R at-a-time, Using Semaphores
- Shared data
- semaphore mutex R //----R processes in
parallel - Process Pi
- do
- wait(mutex)
- critical section
- signal(mutex)
- remainder section
- while (1)
19Semaphore as a General Synchronization Tool
- Execute B in Pj only after A executed in Pi
- Use semaphore flag initialized to 0
- Code
- Pi Pj
- ? ?
- A wait(flag)
- signal(flag) B
20Implementing Semaphores
- How to implement wait?
- wait(S)
- while (S lt 0) //---Busy wait
-
- S-- //---Not atomic?
- How to implement signal?
- signal(S)
- S //---Not atomic?
21Spinlock Binary Semaphore Implementation
- Spinlock binary semaphores implemented with TS
- B FALSE means B 1
- B TRUE means B 0
- wait(B)
- while (TestAndSet(B))
-
- signal(B)
- B false
- Note the busy wait in wait(B)
- Will be avoided in general semaphore
implementation - When used for CS problem, bounded-wait is
violated because while is not indivisible - However, useful in some situations
22Spinlock Semaphore Implementation
- Data structures
- binary-semaphore B11, B20
- int C R
- When C is less than 0 the semaphore value is 0.
- wait operation
- wait(B1) //---Mutex on C
- C--
- if (C lt 0) //---Have to stop here
- signal(B1)
- wait(B2) //---Busy wait
-
- signal(B1)
- signal operation
- wait(B1)
- C
- if (C lt 0)
- signal(B2)
23Semaphore Implementation
- Assume two simple operations
- block(P) moves P to the waiting state, with the
PCB linked into the semaphore list - wakeup(P) moves P to the ready state
24Semaphore Implementation
- wait(P,S)
- wait(B1) //---Short busy wait
- C--
- if (C lt 0)
- block(P)
- signal(B1)
-
- signal(P,S)
- wait(B1) //---Short busy wait
- C
- if (C lt 0)
- wakeup(Someone) //---when and S--
- signal(B1)
- When C is less than 0 the semaphore value is 0.
25Semaphore Implementation Expanded
- wait(P,S)
- while (TestAndSet(B1))
-
- C--
- if (C lt 0)
- block(P)
- B1 FALSE
-
-
- signal(P,S)
- while (TestAndSet(B1))
-
- C
- if (C lt 0)
- wakeup(Someone)
- B1 FALSE
26Bounded-Buffer Problem
- Shared datasemaphore full 0, empty R, mutex
1 - Producer Process
- do
- produce an item in nextp
- wait(empty)
- wait(mutex)
- add nextp to buffer
- signal(mutex)
- signal(full)
- while (1)
- Consumer Process
- do
- wait(full)
- wait(mutex)
- remove an item from buffer to nextc
- signal(mutex)
- signal(empty)
- consume the item in nextc
- while (1)
27Readers-Writers Problem 1
- Shared datasemaphore mutex 1, wrt 1int
readcount 0 //---Number of readers in action -
- Writer Process
- wait(wrt)
- writing is performed
- signal(wrt)
- Reader Process
- wait(mutex) //---Mutex on readcount
- readcount
- if (readcount 1) //---First reader
- wait(wrt) //---Wait to lock out
writers - signal(mutex)
- reading is performed
- wait(mutex)
- readcount--
- if (readcount 0) //---Last reader
- signal(wrt) //---Allow writers
- signal(mutex)
28Dining-Philosophers Problem
- Shared data
- semaphore chopstickN 1
- Philosopher i
- do
- wait(chopsticki)
- wait(chopstick(i1) N)
- eat
- signal(chopsticki)
- signal(chopstick(i1) N)
- think
- while (1)
- Leads to deadlock
- Limit philosophers
- Pickup both at once
- Asymmetric pickup
29Critical Regions
- High-level synchronization construct
- A shared variable v of type T, is declared as
- v shared T
- Variable v accessed only inside statement
- region v when B do S
- where B is a boolean expression.
- Only one process can be in a region at a time.
- When a process executes the region statement, B
is evaluated. - If B is true, statement S is executed.
- If B is false, the process is queued until no
process is in the region associated with v, and B
is tested again
30Example Bounded Buffer
- Shared data
- buffer shared struct
- int pooln
- int count, in, out
-
- Producer
- region buffer when (count lt n) do
- poolin nextp
- in (in1) n
- count
-
- Consumer
- region buffer when (count gt 0) do
- nextc poolout
- out (out1) n
- count--
31Monitors
- High-level synchronization construct that allows
the safe sharing of an abstract data type among
concurrent processes. - monitor monitor-name
- shared variable declarations
- procedure body P1 ()
- . . . //---Can access shared vars and params
-
- procedure body P2 ()
- . . .
-
- procedure body Pn ()
- . . .
-
-
- initialization code
-
-
- Only one process can be executing in a monitor at
a time
32Schematic View of a Monitor
33Monitors
- To allow a process to wait within the monitor, a
condition variable must be declared, as - condition x, y
- Condition variable can only be used with the
operations wait and signal. - The operation
- x.wait()means that the process invoking this
operation is suspended until another process
invokes - x.signal()
- The x.signal operation resumes exactly one
suspended process. If no process is suspended,
then the signal operation has no effect. - Hmmm, which runs, signaller or signalled?
Compromise - signaller must exit the monitor
34Monitor With Condition Variables
35Dining Philosophers Example
- monitor dp
- enum thinking, hungry, eating state5
- condition self5
- void pickup(int i)
- statei hungry
- testi
- if (statei ! eating)
- selfi.wait()
-
- void putdown(int i)
- statei thinking
- test((i4) 5)
- test((i1) 5)
-
- void test(int i)
- if ( (state(i4) 5 ! eating)
- (statei hungry) (state(i1) 5 !
eating)) - statei eating
- selfi.signal()