Title: Process Synchronization
1Process Synchronization
2Chapter 7 Process Synchronization
- Background need for process synchronization
- The Critical-Section Problem protecting
critical only - Synchronization Hardware TestAndSet, Swap
- Semaphores counting and binary, mutual exclude,
synch - Classical Problems buf, read, dine
- Conditional Critical Regions
- Monitors
- Synchronization in Solaris 2 Windows 2000
3High Level Language Constructs
- Semaphores easily can give errors if improperly
used. - Conditional Critical Regions protect access to a
region of code according to a Boolean variable - Monitors protect a set of local variables and
procedures, with programmable synchronization
scheme
4High Level Language Constructs
- Why? Its easy to create hard-to-find errors!
- e.g.
- signal(mutex)
-
- critical section
-
- wait(mutex)
- would leave the critical section unprotected,
with the code working most of the time.
5Critical 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) Swhere B is a boolean
expression. - i.e while statement S is being executed, no
other process can access variable v.
6Critical Regions
- Regions referring to the same shared variable are
mutually exclusive - region v when (true) s1
- region v when (true) s2
- When a process tries to execute the region
statement, the Boolean expression B is evaluated.
- If B is true, statement S is executed.
- If it is false, the process is delayed until B
becomes true and no other process is in the
region associated with v.
7Example Bounded Buffer
- struct buffer
- int pooln
- int count, in, out
-
- region buffer when( count lt n) poolin
nextp in (in1) n count - region buffer when (count gt 0) nextc
poolout out (out1) n count--
Common variables
Producer
Consumer
8Implementing region x when (B) S
- Compiler associates with the shared variable x
the following variables - semaphore mutex
- semaphore first_delay, second_delay int
first_count, second_count - Mutually exclusive access to the critical section
is provided by mutex. - If a process cannot enter the critical section
because the Boolean expression B is false, it
initially waits on the first_delay semaphore,
then is moved to the second_delay semaphore
before it is allowed to reevaluate B.
9Implementing region x when (B) S
- Keep track of the number of processes waiting on
first_delay and second_delay, with first_count
and second_count respectively. - The algorithm assumes a FIFO ordering in the
queuing of processes for a semaphore - for an arbitrary queuing discipline, a more
complicated implementation is required.
10Conditional Region Construct
P1
wait(first_delay)
wait(second_delay)
S
11Conditional Region Construct
Region x when (B) S wait(mutex) while(!B)
first_count if (second_count gt
0) signal(second_delay) else signal(m
utex) wait(first_delay) first_count--
second_count if(first_count gt
0) signal(first_delay) else signal(sec
ond_delay) wait(second_delay) second_count
-- S if (first_count gt 0) signal(first_d
elay) elseif (second_count gt 0) signal(second
_delay) else signal(mutex)
12Monitors
- A synchronization construct with
- local data and processes
- Conditions for waiting
- Only one process at a time is active
- Programmer defines data, processes and conditions
13Monitor Syntax
- monitor monitor-name
-
- shared variable declarations
- procedure body P1 ()
- . . .
-
- procedure body P2 ()
- . . .
-
- procedure body Pn ()
- . . .
-
-
- initialization code
-
-
14Schematic View of a Monitor
15Monitor Conditions
- To allow a process to wait within the monitor, a
condition variable must be declared - condition x
- Condition variable used with 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 (unlike a semaphore).
16Monitor With Condition Variables
17Dining Philosophers
- Define the state of each philosopher
- enum thinking, hungry, eating state5
- Statei eating only if neighbours not eating
- Define a means for a philosopher to delay eating
- condition self5
- Protect the whole with monitor dp.
- Include statei and conditioni
- Include pickup, putdown, test and init
18Dining Philosophers Monitor
- monitor dp
-
- enum thinking, hungry, eating state5
- condition self5
- void pickup(int i) // following slide
- void putdown(int i) // following slide
- void test(int i) // following slide
- void init()
- for (int i 0 i lt 5 i)
- statei thinking
-
-
19Dining Actions
- void pickup(int i)
- statei hungry
- test(i)
- if (statei ! eating)
- selfi.wait()
-
- void putdown(int i)
- statei thinking
- // test left and right neighbours
- test((i4) 5)
- test((i1) 5)
-
void test(int i) if ( (state(i 4) 5 !
eating) (statei hungry)
(state(i 1) 5 ! eating)) statei
eating selfi.signal()
20Dining Philosophers
- dp.init
- fork five processes
- in the ith process
- while(1)
-
- dp.pickup(i)
-
- eat
-
- dp.putdown(i)
-
-
But if the neighbours never put down their forks,
a philosopher could starve!
21Readers-Writers
- fork processes to read and write
- reader()
- while(TRUE)
-
- rw.startRead()
- read the resource
- rw.finishRead()
-
-
-
writer() while(TRUE) rw.startWrite()
read the resource rw.finishWrite()
22Readers- Writers
- monitor reader_writer
-
- int numberOfReaders 0
- boolean busy FALSE
- condition okToRead, okToWrite
- public
- startread
- if (busy (okToWrite.queue)) okToRead.wait
- numberOfReaders
- okayToRead.signal
-
- finishRead
- numberOfReaders--
- if (numberOfReaders 0) okToWrite.signal
-
- startWrite
- if ((numberOfReaders ! 0) busy)
okToWrite.wait - busy TRUE
Returns TRUE if at least one process is suspended.
Nutt, 1997. p. 233.
23Readers-Writers Problem 2
- Reader()
- while(true)
- P(writePending)
- P(readBlock)
- P(mutex1)
- readcount
- if (readCount 1)
- P(writeBlock)
- V(mutex1)
- V(readBlock)
- V(writePending)
- reading is performed
- P(mutex1)
- readcount--
- if (readCount 0)
- V(writeBlock)
- V(mutex1)
-
Writer() while(true)
P(mutex2) writecount if (writecount
1) P(readBlock) V(mutex2)
P(writeBlock) writing is performed V(writ
eBlock) P(mutex2) writeCount-- if
(writeCount 0) V(readBlock) V(mutex2)
24Monitor Implementation using Semaphores
- Define mutex to act as doorway
- A process must execute wait(mutex) before
entering monitor, and signal(mutex) after
leaving. - A process in the monitor can interrupt another
process in the monitor. - Define semaphore next to allow process queuing
inside the monitor.
25Monitor Implementation using Semaphores
- Variables
- semaphore mutex // (initially 1)
- semaphore next // (initially 0)
- int next_count 0
- Each external procedure F will be replaced by
- wait(mutex)
-
- body of F
-
- if (next_count gt 0)
- signal(next)
- else
- signal(mutex)
- Mutual exclusion within a monitor is assured.
Counts the number of variables suspended on next
26Implementation of Monitor Conditions
- For each condition variable x, we have
- semaphore x_sem // (initially 0)
- int x_count 0
x.signal
x.wait
if (x_count gt 0) next_count signal(x_sem) w
ait(next) next_count--
x_count if (next_count gt 0) signal(next) else
signal(mutex) wait(x_sem) x-count--
27Monitor Implementation
- Several processes could be suspended on condition
x. Which one would be reawakened first? - Define conditional-wait construct
- x.wait(c)
- c integer expression evaluated when the wait
operation is executed. - value of c (a priority number) is stored with the
name of the process that is suspended. - when x.signal is executed, the process with
smallest associated priority number is resumed
next.
28Resource Allocation Monitor
- monitor ResourceAllocation
-
- boolean busy
- condition x
- void acquire(int time)
- if (busy)
- x.wait(time)
- busy true
-
- void release()
- busy false
- x.signal()
-
- void init()
- busy false
-
29CallingResource Allocation
- ResourceAllocation R
- fork several processes
- in each process
- R.acquire(t)
-
- access the resource
-
- R.release()
Requesting process indicates time to use the
resource. Still requires careful coding to use
the monitor for fair access to the resource.
30Monitor Implementation
- Check two conditions to establish correctness of
system - User processes must always make their calls on
the monitor in a correct sequence. - Must ensure that an uncooperative process does
not ignore the mutual-exclusion gateway provided
by the monitor, and try to access the shared
resource directly, without using the access
protocols. - Difficult to check for a large, dynamic system.
- Use access control (Chapter 18)
31Solaris 2 Synchronization
- Implements a variety of locks to support realtime
multithreaded code running on multiple CPUs. - adaptive mutexes for efficiency when protecting
short code segments - Spinlock if waiting on a running process, sleep
if waiting on a sleeping process (in multiCPU).
Sleep only for uniprocessor. - condition variables and readers-writers locks
when longer sections of code need access to data. - Best for data accessed frequently in read-only
mode. - turnstiles to order the list of threads waiting
to acquire either an adaptive mutex or
reader-writer lock. - Queue structure for threads blocked on a lock
32Windows 2000 Synchronization
- Implements a variety of locks to support realtime
multithreaded code running on multiple CPUs. - Protection for global resources
- Spinlocks on multiprocessor systems
- Interrupt masks on uniprocessor systems.
- Also provides dispatcher objects which may act as
mutexes, semaphores or events. - Mutex ownership and release to protect shared
data - Events notify a waiting thread when a desired
condition occurs (much like a condition
variable). - Dispatcher objects states
- signaled an object is available threads do not
block - Nonsignaled an object is not available threads
block wait
33Database Integrity
- Transaction a collection of operations that
forms a single logical function. - A successfully completed transaction is
committed if unsuccessful, it is aborted. - If curtailed by system failure, data partly
affected must be rolled back. - Recovery
- Log-based record id, old and projected new data
- At checkpoints, move log from volatile to stable
storage
34Database Integrity
- Concurrency control
- Atomic transactions could be in any order, but
efficiency can be gained by allowing concurrency. - Define conflict serializable schedule of
operations, so non-conflicting operations can be
run concurrently and arranged in optimal
sequences. - Locking Protocols
- Shared for reading, but not for writing
- Exclusive for reading or writing
- Growing transaction collects locks before
releasing - Shrinking transaction releases locks, refuses
new ones
35Database Integrity
- Timestamp-Based Protocols
- Timestamp by system clock or logical counter
- Associate with each data item
- W-timestamp timestamp of last write
- R-timestamp timestamp of last read
- Rules for reading
- If read TS lt W-timestamp, reject read request
- If read TS gt W-timestamp, accept
- Rules for writing
- If write TS lt R-timestamp, reject as not expected
- If write TS lt W-timestamp, reject attempt as
obsolete - If write TS gt W-timestamp, accept