Process Synchronization - PowerPoint PPT Presentation

1 / 112
About This Presentation
Title:

Process Synchronization

Description:

Process B reads 'in', changes its contents to his job and moves 'in' by one ... rw for read/write; ne for non-empty. Receive(): send(): down(ne); down(rw) ... – PowerPoint PPT presentation

Number of Views:120
Avg rating:3.0/5.0
Slides: 113
Provided by: csBg
Category:

less

Transcript and Presenter's Notes

Title: Process Synchronization


1
Process Synchronization
  • Race Conditions
  • Example Spooler directory with slots index
    variable two processes attempt concurrent access

Process A
5
6
7
4
. . .
. . .
prog1
prog2
prog3
In7
Process B
Out 4
2
Race Conditions...
  • Process A reads in and is switched..
  • Process B reads in, changes its contents to his
    job and moves in by one
  • Process A gets the control and changes the
    contents of his in to his job and moves the
    value of in by one
  • Result in has a correct value but the
    printing job of B is lost.
  • Comment common data structures to A, B

3
Critical Sections
  • Mutual Exclusion
  • Critical section
  • Conditions needed
  • No two processes in critical sections
    simultaneously
  • Process outside its critical section may not
    block another process
  • There is a limit on the number of times a process
    can enter the CS while another waits (i.e. no
    starving)
  • No assumptions about speeds, no. of cpus, etc.
  • 1st condition avoids race condition, but is not
    sufficient for correct concurrent cooperation

4
Critical Regions
  • Mutual exclusion using critical regions

5
Mutual Exclusion - attempts...
  • 1. Disable interrupts
  • Violates condition 3 or 2(forgot to enable)
  • Too much responsibility for a user process
  • 2. Lock variables
  • If Lock 0 then set it to 1 and enter CS
  • else wait...
  • Race conditions occur when context is changed
    between read 0 and write 1

6
another attempt
  • 3. Strict alternation -
  • while (TRUE)
  • while (turn ! 0) / wait /
  • critical_section()
  • turn 1
  • non_critical_section()
  • Violation process blocked by another process
    outside its critical section!!
  • while (TRUE)
  • while (turn ! 1) / wait /
  • critical_section()
  • turn 0
  • non_critical_section()

7
Petersons Solution
  • define FALSE 0
  • define TRUE 1
  • define N 2
  • int turn / whose turn is it ? /
  • int interestedN / all initially 0
    (FALSE) /
  • void enter_region(int process) / who is
    entering 0 or 1 ? /
  • int other / number of other process /
  • other 1- process / opposite of process
    /
  • interested(process) TRUE / signal that
    youre interested /
  • turn process / set flag /
  • while (turn process
  • interested(other) TRUE) / null statement
    /
  • void leave_region(int process) / who is
    leaving 0 or 1 ? /
  • interested(process) FALSE / departure from
    critical region /

8
For any Solution
  • Need to Prove
  • Mutual Exclusion - No two processes are in their
    respective CS at the same time
  • Progress - a process outside its CS cannot block
    a process waiting to enter a CS
  • Bounded waiting (no Starvation) - no process
    waits indefinitely to enter its CS

9
Petersons Solution - observations
  • Solution for two processes only
  • For N processes some numbering of the queue is
    needed..
  • Uses busy-wait
  • Memory writes are assumed to be atomic
    interested lt-- TRUE
  • a basic assumption for all solutions is
  • No Process dies inside a critical section

10
and for N Processes ...
  • int valueN / processes get waiting
    numbers /
  • int busyN / just a flag... /
  • void enter_region(int i ) / process i
    entering.. /
  • busy(i) TRUE / guard the value selection
    /
  • value(i) max(value(0), value(1), ,
    value(N-1)) 1 / LAST in line /
  • busy(i) FALSE
  • for(k0 k lt N k )
  • while (busy(k) TRUE) / wait before
    checking /
  • while((value(k) ! 0) ((value(k), k) lt
    (value(i), i))) / wait /
  • void leave_region(int i )
  • value(i ) 0

11
Using the Hardware - TSL instruction
  • TSL - Test and Set Lock
  • read a memory word into a register AND store a
    nonzero value into that word, in an indivisible
    instruction sequence
  • enter_region
  • tsl R1,flag copy flag to R1 and set flag
    to 1
  • cmp R1,0 was flag 0 ?
  • jnz enter_region if not zero, Lock was set, so
    loop
  • ret return enter critical region
  • leave_region
  • mov flag,0 set flag to 0
  • ret return critical region left

12
Implement fairness with TSL
  • test_and_set(int flag) - TSL 1,flag and
    return(flag)
  • interested(i) TRUE
  • test TRUE
  • while(interested(i) TRUE test TRUE)
  • test test_and_set(lock)
  • interested(i) FALSE
  • . . . critical section . . .
  • j i1 n
  • while(j ! i !(interested(j))) j n
  • if(j i) lock FALSE
  • else interested(j) FALSE

13
Synchronization Constructs - Semaphores
  • Two operations define a semaphore S
  • DOWN(S) p(s)
  • while(s lt 0)
  • s s - 1
  • UP(S) v(s)
  • s s 1
  • Operations on the counter are performed
    indivisibly
  • S is non-negative

14
Synchronizing with Semaphores
  • Mutual Exclusion
  • down(mutex)
  • critical section
  • up(mutex)
  • Synchronization
  • requirement S2 executed after S1 is completed
  • Synch 0
  • P1 S1 P2 DOWN(Synch)
  • UP(Synch) S2

15
deadlocks with Semaphores...
  • Two processes p0 and p1
  • Two semaphores Q and S
  • p0 p1
  • down(S) down(Q)
  • down(Q) down(S)
  • . ..
  • up(S) up(Q)
  • up(Q) up(S)
  • p0 does the first line, then p1 and so on...

16
More on Synchronization...
  • Three processes p1 p2 p3
  • semaphores s1 1, s2 0
  • p1 p2 p3
  • down(s1) down(s2) down(s2)
  • .. code .. .. code .. .. code ..
  • up(s2) up(s2) up(s1)
  • the ordering of the processes is (p1(p2p3))
  • --gt ordering can be done by events (on a clock)

17
Whats wrong with busy waiting
  • Wastes cpu time by waiting
  • Side effects
  • Two processes with different priorities arrive at
    their critical section in an order inverse to
    their priorities
  • The higher priority process gets time-slices
  • The lower priority process cannot complete its
    processing of its critical section and leave !
  • Priority Inversion

18
1st attempt - sleep and wakeup
  • sleep() is a system call that blocks the calling
    process indefinitely
  • wakeup(p) unblocks process p
  • A process calls sleep() when it tries to enter
    and finds that the lock is true
  • enter if (lock) call sleep()
  • Each process calls wakeup(other) when leaving the
    critical section...
  • leave lock false wakeup(other)

19
Problems with sleep() and wakeup()
  • Process 0 checks lock TRUE and is blocked
    before putting itself to sleep
  • Process 1 generates a wakeup(process 0), after
    leaving its critical section
  • The system call wakeup(process 0) is wasted
    because process 0 is not yet sleeping
  • Process 0 is unblocked later and calls sleep()
  • Process 1 has to go through its CS again, to
    wakeup process 0

20
Concrete problem - bounded buffer
  • Two processes (at least) use a shared buffer in
    memory
  • The buffer is finite (i.e. bounded)
  • One process writes on the buffer and the other
    process reads from it
  • A full buffer stops the writer (producer)
  • An empty buffer stops the reader (consumer)

21
Bounded Buffer with sleep(), wakeup()
  • A producer process calls sleep() when the mutual
    buffer is full
  • A consumer process calls sleep() when the mutual
    buffer is empty
  • Each process calls wakeup(other) when some
    condition on the mutual buffer is true

22
Producer-consumer with sleep and wakeup
  • define N 100 / size of buffer /
  • int count 0 / number of items in buffer
    /
  • void producer(void)
  • int item
  • while(TRUE) / forever... /
  • produce_item(item) / produce an item /
  • if (count N) sleep() / go to sleep if
    buffer is full /
  • enter_item(item) / insert item into buffer
    /
  • count count 1 / increment count of items
    /
  • if (count 1) wakeup(consumer) / was
    buffer empty ? /

23
Producer-consumer with sleep and wakeup
  • void consumer(void)
  • int item
  • while(TRUE) / forever... /
  • if (count 0) sleep() / go to sleep if
    buffer is empty /
  • remove_item(item) / remove item from
    buffer /
  • count count - 1 / increment count of
    items /
  • if (count N - 1) wakeup(producer) / was
    buffer full ? /
  • consume_item(item) / print item /

24
Race conditions with sleep() and wakeup()
  • Consumer checks buffer0 and is blocked before
    putting itself to sleep
  • Producer generates a wakeup(consumer), based on
    an empty buffer
  • The system call wakeup(consumer) is wasted
    because consumer is not yet sleeping
  • Consumer is unblocked later and calls sleep()
  • Producer continues running and fills up the
    buffer, then calls sleep().
  • Both processes sleep forever

25
Semaphores with blocking (Dijkstra 1965)
  • An integer counter S
  • Operation DOWN
  • if S gt 0 decrement S,
  • else sleep
  • Operation UP
  • If (S 0 there are sleeping processes) wake
    one up (S remains 0) ,
  • else increment S
  • this semaphore has only nonnegative values
  • comment UP and DOWN are atomic operations

26
Negative-valued Semaphores
  • An integer counter S
  • Operation DOWN
  • decrement S and check value, if S lt 0, sleep
  • Operation UP
  • increment S , if processes are sleeping (S lt 0)
    , wake one up
  • a semaphore may have negative values
  • the magnitude of the negative value is the
    number of waiting processes
  • negative values arise because of the switching
    of lines of decrement and check (from the
    classical semaphore)

27
Semaphores for the Producer-Consumer problem
  • define N 100 / Buffer size /
  • typedef int semaphore
  • semaphore mutex 1 / access control to
    critical section /
  • semaphore empty N / counts empty buffer slots
    /
  • semaphore full 0 / full slots /
  • void producer(void)
  • int item
  • while(TRUE)
  • produce_item(item) / generate something...
    /
  • down(empty) / decrement count of empty /
  • down(mutex) / enter critical section /
  • enter_item(item) / insert into buffer /
  • up(mutex) / leave critical section /
  • up(full) / increment count of full slots /

28
Semaphores for the Producer-Consumer problem
  • void consumer(void) int item while(TRUE)
    down(full) / decrement count of full
    / down(mutex) / enter critical section
    / remove_item(item) / take item from buffer)
    / up(mutex) / leave critical section
    / up(empty) / update count of empty
    / consume_item(item) / do something...
    / Comment up() and down() are simple
    atomic operations

29
Semaphores for the mailboxes ...
  • In the 1st assignment a thread using receive()
    blocks on an empty mailbox and mailboxes have to
    be protected for read/write
  • two semaphores (unbounded buffer)
  • rw for read/write ne for non-empty
  • Receive() send()
  • down(ne) down(rw)
  • down(rw) add_message
  • read_message up(ne)
  • up(rw) up(rw)
  • .. ...

30
Bounded-buffer for messages
  • Threads use the system call send() to send
    messages, which are then stored in threads
    mailboxes (Shell mailbox)
  • The buffer of all mailboxes is bounded and so
    send() is a producer and the receive() function
    that extracts the messages from the threads
    (Shell) mailboxes is a consumer
  • These two functions must use one common
    semaphore, empty, initialized to the (user
    defined) size of the buffer N.
  • The implementation of a bounded-buffer, makes
    use of an ne semaphore for each thread

31
Implementation of Semaphores
  • struct semaphore
  • int value, flag // flag is a variable for
    testset - true when 0
  • list_proc L
  • DOWN(S) repeat until testset(S.flag)
  • S.value S.value - 1
  • if(S.value lt 0)
  • add process to S.L
  • set-up p as blocked
  • S.flag 0
  • --gt scheduler
  • else S.flag 0
  • UP(S) repeat until testset(S.flag)
  • S.value S.value 1
  • if(S.value lt 0)
  • remove a process P from S.L
  • wakeup(P)
  • S.flag 0

32
Atomicity of Semaphores
  • The use of TSL can work for several cpus,
    enabling access of only one cpu at a time to the
    semaphore itself
  • For a single cpu one can simply use disable
    interrupts
  • The use of disable interrupts is limited to
    several lines of (system) code
  • acceptable for the system to do so
  • locks with the TSL instruction - busy-waiting

33
Implementation of Semaphores Disabling
Interrupts
  • Wait(s)
  • inhibit interrupts
  • s.count s.count-1
  • if s.countlt0
  • then begin
  • place this process in s.queue
  • block this process and allow interrupts
  • end
  • else allow interrupts
  • Signal(s)
  • inhibit interrupts
  • s.count s.count1
  • if s.count 0
  • then begin
  • remove a process P from s.queue
  • place process P on ready list
  • end
  • allow interrupts

34
Semaphores Busy-Wait
  • With previous solutions a process was
    Busy-waiting during the Entire critical section
    of another process - may be a long time!
  • Now a process is busy-waiting only during the
    short CS of updating the semaphores counter!

35
Counting and Binary semaphores
  • binary-semaphore S1, S2
  • down(S) up(S)
  • down(S1) down(S1)
  • S.value-- S.value
  • if(S.value lt 0) if(S.value lt 0) up(S2)
  • up(S1) up(S1)
  • down(S2)
  • else up(S1)
  • This is the negative implementation of a
    general semaphore

36
Mutex binary semaphores
  • In user space (Solaris) one can use TSL
  • mutex_lock
  • TSL REG, mutex
  • CMP REG, 0
  • JZE ok the opposite of enter_region
  • CALL queue_thread or thread_yield
  • ok
  • RET
  • mutex_unlock
  • MOV mutex, 0
  • RET
  • queue_thread is a call to a user-space scheduler
    and thus no kernel context switch is necessary.
    In real life additional functions are supported,
    like try_lock()

37
Semaphores
  • Binary vs. General Semaphores
  • No or very little Busy-Wait
  • Can be used to solve both Mutual exclusion and
    Synchronization problems
  • Need to be careful to avoid Deadlocks
  • The shared variable problem

38
Choices of the New Generation
  • Load-linked/store-conditional(DECs Alpha AXP,
    IBMs PowerPC, MIPS R4000)
  • Two complementary operationsRead from address
    XIf there was no write to X since your last
    LL(X)Write V on Xelse FailMore power to LL/SC
    then TSLPossible to implement atomic
    incrementPossible to identify multiple writes of
    the same value

39
Implementing Locks with LL/SC
  • Use variable L(0 free, 1 used)
  • Lock-Acquire(L)
  • A LL(L) if L then goto A if SC(L,1) then
    goto A
  • Lock-Release(L)
  • L 0

40
Event Counters
  • Integer counters with three operations
  • Advance(E) increment (atomically) E by 1 wake
    up relevant sleepers
  • Await(E,v) wait until E gt v. sleep if E lt v.
  • Read(E) returns the current value of E
  • Only increase, never decrease
  • For the EC implementation of a bounded-buffer
    problem no Read() is needed. Only for absolute
    synchronization

41
producer-consumer with Event Counters
  • define N 100typedef int event_counter event
    _counter in 0 / counts inserted items
    /event_counter out 0 / items removed from
    buffer /void producer(void)int item,
    sequence 0
  • while(TRUE) produce_item(item) sequence
    sequence 1 / counts items produced
    / await(out, sequence - N) / wait until
    buffer has room / enter_item(item) / insert
    into buffer / advance(in) / inform
    consumer /

42
Event counters (producer-consumer)
  • void consumer(void) int item, sequence
    0 while(TRUE) sequence sequence
    1 / count items produced /
    await(in, sequence) / wait for item
    / remove_item(item) / take item from
    buffer / advance(out) /
    inform producer / consume_item(item)

43
Message Passing - avoiding former problems
  • For several cpus with their own memories
    semaphores cannot provide mutual exclusion
  • Implement synchronization by system calls
  • Issues
  • Sometimes an acknowledgement is needed
  • A reliable address for processes (domains..)
  • message ID to avoid duplication
  • Authentication (validate the senders ID)
  • Two main functions
  • send(destination, message)
  • receive(source, message) block while
    waiting...
  • To avoid accessing a processs address space -
    mailboxes

44
Producer-consumer with Message Passing
  • define N 100
  • define MSIZE 4 / message size /
  • typedef int message(MSIZE)
  • void producer(void)
  • int item
  • message m / message buffer /
  • while(TRUE) produce_item(item)
  • receive(consumer, m) /wait for an empty /
  • construct_message(m, item)
  • send(consumer, m) / send item /

45
Message passing (cont.)
  • void consumer(void)int item, imessage
    mfor(i 0 i lt N i) send(producer, m)
    / send N empties / / Storage is up to the
    OS /
  • while(TRUE) receive(producer, m) / get
    message with item / extract_item(m,
    item) send(producer, m) / send an empty
    reply / consume_item(item)

46
Messages - comments
  • Unix pipes - a generalization of messages no
    fixed size message (blocking receive)
  • Mailboxes take on the responsibility of
    maintaining the buffer..
  • Mailboxes can serve as an alternative address for
    a process (instead of PID)
  • If no buffer is maintained by the system, then
    every receive can only be run after a send call
    this Rendezvous

47
Equivalence Message passing with Semaphores
  • Each process has an associated semaphore,
    initially 0, on which to block while waiting for
    a send or receive
  • A shared buffer area contains mailboxes, each one
    containing an array of message slots
  • Slots are chained together, to keep their
    receiving order, and there are counters of full
    slots and of empty slots
  • Mailboxes also contain a pointer to queue of
    unable_to_send_to processes and a pointer to
    queue of unable_to_receive_from
  • This orders up operations for the waiting process
    in a queue
  • The whole shared buffer must be protected by a
    binary semaphore, so that only one process can
    inspect or update the shared data structures

48
Message passing with Semaphores
  • Performing a send on a mailbox that contains at
    least one empty slot - inserts a message, updates
    counters and links
  • Performing a receive on an empty mailbox - enters
    itself on the receive queue, up on mutex, down on
    its own semaphore
  • When the receiving process is awakened - down on
    mutex
  • Performing a send that has an empty slot - after
    inserting the message, the sender checks the
    waiting queue, if not empty removes the first
    process and performs an up on its semaphore
  • The sender leaves the critical region following
    the above up operation, and the mutex semaphore
    is treated very similarly to the example
    implementation of monitors.
  • Performing a send to a full mailbox - enters
    itself on the send queue, up on mutex, down on
    its own semaphore

49
Equivalence Semaphores with Message passing
  • use a semaphore-process (mailbox) p
  • p keeps the counter of the semaphore s
  • p1 down(s) - send(p,down(s))
  • receive(p,ack)
  • if s lt 0 p does not send an acknowledgement
  • P2 up(s) - send(p,up(s))
  • if s lt 0 p sends the acknowledgement to a
    selected process send (pi, ack)
  • Advantage porting code to the distributed
    world

50
Monitors - high level synchronization constructs
  • Semaphores and event-counters are too primitive
    (low level) and are hard to program
  • Monitors are a special package of procedures
  • Mutual exclusion constructs are generated by the
    compiler. Internal data structures are invisible
  • Only one process is active in a monitor at the
    same time - high level mutual exclusion
  • monitor sharedData
  • int buffer
  • public
  • writeData(int byteNum)
  • readData(int byteNum)

51
  • type monitor-name monitor
  • variable declarations
  • procedure entry P1 ()
  • begin end
  • procedure entry P2 ()
  • begin end
  • .
  • .
  • .
  • procedure entry Pn ()
  • begin end
  • begin
  • initialization code
  • end

52
Monitors - Condition variables
  • Only one process is active in a monitor at the
    same time - high level mutual exclusion
  • To enable synchronization Condition variables
    and operations on them wait and signal
  • the monitor provides queuing for waiting
    procedures
  • When one procedure waits and another signals,
    the signaling procedure is inside the monitor !!!
  • Operation signal must be either followed by
    block() or exit_monitor, so that only one
    procedure is active at one time

53
Bounded-Buffer with Monitors
  • monitor ProducerConsumer
  • condition full, empty
  • integer count
  • procedure enter
  • begin if count N then wait(full)
  • enter_item
  • count count 1
  • if count 1 then signal(empty) end
  • procedure remove
  • begin if count 0 then wait(empty)
  • remove_item
  • count count - 1
  • if count N - 1 then signal(full) end
  • count 0
  • end monitor

54
Bounded-Buffer with Monitors (II)
  • procedure producer
  • begin while true do
  • begin
  • produce_item
  • ProducerConsumer.enter
  • end
  • end
  • procedure consumer
  • begin while true do
  • begin
  • ProducerConsumer.remove
  • consume_item end
  • end

55
Monitors - some comments
  • Condition variables do not accumulate signals,
    for later use
  • wait() must come before signal()
  • Unlike sleep() and wakeup(), no race conditions,
    because monitors have mutual exclusion
  • More complex implementation than semaphores,
    compilers construct instead of system calls Up
    Down
  • Why not implemented?
  • How to interpret nested monitors ?
  • How to define wait, priority scheduling,
    timeouts, aborts ?
  • How to Handle all exception conditions ?
  • How to interact with process creation and
    destruction ?

56
Monitors vs. Java
  • Solution to producer-consumer problem in Java
    (part 1)

57
Monitors vs. Java (Cont.)
  • Solution to producer-consumer problem in Java
    (part 2)

58
Equivalence Implementing Monitors with
Semaphores - problems
  • typedef int semaphore
  • semaphore mutex1 /control access to monitor/
  • void enter_monitor(void)
  • down(mutex) /only one-at-a-time/
  • void leave(void)
  • up(mutex) /allow other processes in/
  • void leave_with_signal(semaphore c) /c
    signals for leave/
  • up(c) /of the condition variable/
  • Void wait(semaphore c) /block on a condition/
  • /c is the condition/
  • up(mutex) /allow other processes/
  • down (c) /block on the condition/

59
Implementing Monitors with SemaphoresCorrect!
  • semaphore mutex 1 / control access to
    monitor /
  • cond c / c countsemaphore /
  • void enter_monitor(void)
  • down(mutex) / only one-at-a-time /
  • void leave(void)
  • up(mutex) / allow other processes in /
  • void leave_with_signal(cond c) / cond
    c is a struct /
  • if(c.count 0) up(mutex) / no waiting,
    just leave.. /
  • else c.count--
  • up(c.s)
  • void wait(cond c) / block on a condition
    /
  • c.count / count waiting processes /
  • up(mutex) / allow other processes /
  • down(c.s) / block on the condition /

60
Barriers
  • Use of a barrier
  • processes approaching a barrier
  • all processes but one blocked at barrier
  • last process arrives, all are let through

61
Dining Philosophers (1)
  • Philosophers eat/think
  • Eating needs 2 forks
  • Pick one fork at a time
  • How to prevent deadlock
  • What about Starvation?

62
The dining (chinese) philosophers - problem
  • Each process needs two resources
  • Every resource is mutual to two processes - i.e.
    every pair of processes compete for a specific
    resource
  • Every process can either be assigned two
    resources or none at all
  • Every process that is waiting for its two
    resources should sleep (be blocked)
  • Every process that releases its two resources
    must wake-up the two competing processes for
    these resources, if they are interested.

63
The dining (chinese) philosophers - problem
  • define N 5
  • void philosophers(int i)
  • while(TRUE)
  • think()
  • take_stick(i) / left stick /
  • take_stick(i1) N) / right stick /
  • eat()
  • put_stick(i)
  • put_stick((i1) N)
  • replace take_stick(i) by down(i) put_stick(I)
    by up(I)

64
Dining philosophers (soltn.)
  • define N 5
  • define LEFT (i-1) N
  • define RIGHT (i1) N
  • define THINKING 0
  • define HUNGRY 1
  • define EATING 2
  • typedef int semaphore
  • int stateN
  • semaphore mutex 1
  • semaphore sN / per each philosopher /
  • void philosopher(int i)
  • while(TRUE)
  • think()
  • pick_sticks(i)
  • eat()
  • put_sticks(i)

65
pick_sticks(i) put_sticks(i) test(i)
  • void pick_sticks(int i)
  • down(mutex) / enter CS /
  • statei HUNGRY
  • test(i) / try for 2 sticks /
  • up(mutex) / exit CS /
  • down(si) / block if sticks were not
    acquired../
  • void put_sticks(int i)
  • down(mutex)
  • statei THINKING / finished eating../
  • test(LEFT) / can left neighbour eat now ? /
  • test(RIGHT) / .. RIGHT.. ? /
  • up(mutex)
  • void test(int i)
  • if(statei HUNGRY stateLEFT ! EATING
    stateRIGHT ! EATING)
  • statei EATING
  • up(si)

66
Chinese Philosophers - Monitor
  • monitor diningPhilosophers
  • condition selfN
  • integer stateN
  • procedure pick_sticks(i)
  • begin statei HUNGRY
  • test(i)
  • if statei ltgt EATING then wait(selfi)
  • end
  • procedure put_sticks(i)
  • begin
  • statei THINKING
  • test(LEFT)
  • test(RIGHT)
  • end

67
Chinese Philosophers - Monitor (II)
  • non-entry-procedure test(i)
  • begin
  • if stateLEFT ltgt EATING
  • and stateRIGHT ltgt EATING
  • and statei HUNGRY
  • then begin
  • statei EATING
  • signal(selfi)
  • end
  • end
  • for i 0 to 4 do statei THINKING
  • end monitor

68
Dining Philosophers Deadlocks Starvation
  • the solution is deadlock-free because every
    process has either two resources or none
  • for deadlock a process must have one resource
    and block for the other that is owned by another
    process (which is blocked waiting for the
    first)..
  • Starvation is possible
  • Process 1 2 3 4 5
  • eating-state e e
  • e e
  • e e
  • e e

69
The Sleeping Barber Problem
70
..yet another synchronization problem - the
sleeping barber
  • barber shop - one service provider many
    customers
  • Finite capacity of shop - finite waiting queue
  • One customer is served at one time
  • Service provider, barber, sleeps when no
    customers are waiting
  • Customer leaves if shop is full
  • Customer sleeps while waiting in queue
  • Use two semaphores - barber waits for customers
    customers wait for barbers count queue length..

71
..yet another synchronization problem - the
sleeping barber
  • define CHAIRS 5
  • typedef int semaphore
  • semaphore customers 0
  • semaphore barbers 0
  • semaphore mutex 1
  • int waiting 0
  • void barber(void)
  • while(TRUE)
  • down(customers) / block if no customers /
  • down(mutex) / access to waiting /
  • waiting waiting - 1
  • up(barbers) / barber is in.. /
  • up(mutex) / release waiting /
  • cut_hair()

72
The sleeping barber
  • void customer(void) down(mutex) / enter
    CS / if(waiting lt CHAIRS) waiting
    waiting 1 / increment waiting
    / up(customers) / wake up barber
    / up(mutex) / release waiting
    / down(barbers) / block for 0 barbers
    / get_haircut() else
    up(mutex) / shop full .. leave /

73
Readers and Writers
  • typedef int semaphoresemaphore mutex
    1semaphore db 1int rc 0 / of
    reading processes /
  • void reader(void) while(TRUE)
    down(mutex) / exclusive access to rc /
    rc rc 1 if(rc 1) down(db) / first
    reader.. ? / up(mutex) / release rc
    / read_data_base() down(mutex) /
    exclusive access to rc / rc rc - 1
    if(rc 0) up(db) / last reader ? /
    up(mutex) / release rc / void
    writer(void) while(TRUE) down(db) /
    get exclusive access / write_data_base()
    up(db)

74
Readers and Writers
  • No reader is kept waiting, unless a writer has
    already obtained the db semaphore
  • a second version of the readers-writers problem
    requests that no writer is kept waiting once it
    is ready - when a writer is waiting, no new
    reader can start reading
  • In both cases processes may starve - writers in
    the first version and readers in the second
    version...

75
Improve writers priority...
  • typedef int semaphoresemaphore mutex 1,
    mutex1 1semaphore db 1, rdb 1int rc
    0, wc 0 / count readers and writers /
  • void reader(void) void writer(void)
    while(TRUE) while(TRUE) down(rdb)
    down(mutex1)
  • down(mutex) wc wc
    1 rc rc 1
    if(wc 1) down(rdb) if(rc 1)
    down(db) up(mutex1)
    up(mutex) down(db)
    up(rdb) write_data_base()
  • read_data_base() up(db)
    down(mutex) down(mutex1) rc rc -
    1 wc wc -1 if(rc 0) up(db) if(wc
    0) up(rdb) up(mutex)
    up(mutex1)

76
Readers-writers with Monitors
  • Monitor reader_writer
  • int numberOfReaders 0
  • boolean busy FALSE
  • condition okToRead, okToWrite
  • public
  • startRead
  • if(busy (okToRead.queue)) okToRead.wait
  • numberOfReaders numberOfReaders 1
  • okToRead.signal
  • finishRead
  • numberOfReaders numberOfReaders - 1
  • if(numberOfReaders 0) okToWrite.signal

77
Readers-writers with Monitors (II)
  • startWrite
  • if((numberOfReaders ! 0) busy)
    okToWrite.wait
  • busy TRUE
  • finishWrite
  • busy FALSE
  • if(okToWrite.queue)
  • okToWrite.signal
  • else
  • okToRead.signal

78
Passing through a one-way Tunnel
  • One-way tunnel enables any number of processes
    in the same direction
  • a process in the right direction cannot enter
    if there is at least one process in the left
    direction inside the tunnel
  • Similar to Readers-Writers
  • a solution must count2 the number of processes
    inside the tunnel (in each direction)
  • a semaphore should be used for use of the
    tunnel, call it busy
  • waiting processes block on another semaphore
    waiting2
  • two functions (that use a semaphore for mutual
    exclusion) arrive(int direction) and leave(int
    direction) are performed by entering and leaving
    processes

79
One-way tunnel - solution
  • int count2
  • semaphore mutex 1, busy 1
  • semaphore waiting2 1,1
  • void arrive(int direction) void leave(int
    direction)
  • down(waitingdirection) down(mutex)
  • down(mutex) countdirection - 1
  • countdirection 1
    if(countdirection 0)
  • if(countdirection 1) up(busy)
  • up(mutex) up(mutex)
  • down(busy)
  • else up(mutex)
  • up(waitingdirection)

80
Deadlocks
  • Deadlock of Resource Allocation
  • Process A requests and gets Laser Printer
  • Process B requests and gets Fast Modem
  • Process A requests Fast Modem and blocks
  • Process B requests Laser Printer and blocks
  • Deadlock situation Neither process can move and
    no process can release its allocated device
    (Resource)
  • Comment both of the above resources (devices)
    have exclusive access

81
Resources
  • Resources - Tapes, Disks, Printers, Database
    Records, etc.
  • Some resources are non-preemptable (i.e. printer)
  • Preemptable resources are easy (main memory)
  • Resource allocation procedure
  • Request
  • Use
  • Release only at the end and leave
  • Block process while waiting for Resources

Iterate
82
Defining Deadlocks
  • A set of processes is deadlocked if each process
    is waiting for an event that can only be caused
    by another process in the set.
  • Necessary conditions for deadlock
  • 1. Mutual exclusion resource used by only one
    process
  • 2. Hold and wait process can request resource
    while holding another resource
  • 3. No preemption only process can release
    resource
  • 4. Circular wait 2 or more processes waiting for
    resources held by other (waiting) processes

83
Modelling deadlocks
  • modelled by a directed graph (resource graph)
  • Requests and assignments as directed edges
  • Processes and Resources as vertices
  • Cycle in graph means deadlock

F
P
A
S
R
Q
B
M
84
the occurance of deadlocks
85
A Resource Allocation Graph
86
Resource Allocation Graph With A Deadlock
87
A Cycle But No Deadlock
88
Basic Facts
  • If graph contains no cycles ? no deadlock.
  • If graph contains a cycle ?
  • if only one instance per resource type, then
    deadlock.
  • if several instances per resource type,
    possibility of deadlock.

89
Dealing with Deadlocks
  • Possible Strategies
  • Prevention
  • structurally negate one of the four necessary
    conditions
  • Avoidance
  • allocate resources carefully, so as to avoid
    deadlocks
  • Detection and recovery
  • Do nothing (Ostrich algorithm)
  • deadlocks are rare and hard to tackle... do
    nothing
  • Unix - process table with 1000 entries and 100
    processes each requesting 20 FORK calls...
    deadlock
  • users prefer a rare deadlock on frequent refusal
    of FORK

90
Deadlock prevention
  • Attack one of the 4 necessary conditions
  • 1. Mutual exclusion
  • Minimize exclusive allocation of devices
  • Use spooling (not good for all devices - Tapes
    Process Tables) may fill up spools (disk space
    deadlock)...
  • 2. Hold and Wait
  • Request all resources immediately (before
    execution)
  • Problem not known initially, inefficient
  • or
  • to get a new resource, free everything, then
    request everything again (including new resource)

91
...Attack one of the 4 necessary conditions
  • 3. No preemption
  • causes incorrect execution...
  • ... without the process knowing it
  • 4. Circular wait condition
  • Allow holding only single resource (bad idea)
  • Number resources, allow requests only in
    ascending order
  • Request only resources numbered higher than
    anything currently held
  • Not a workable solution - may have no solution

92
Deadlock Avoidance
  • System grants resources only if it is safe
  • basic assumption maximal request per process is
    known
  • Example 2 processes and 2 devices (Printer
    Plotter)

93
Bankers Algorithm (single resource)
  • Simulate allocation of resources
  • Bankers Algorithm (Dijkstra 1965)1. Pick a
    process that can terminate after fulfilling the
    request (enough free resources)2. Free all its
    resources(simulation)3. Mark process
    terminated4. If all processes marked, report
    safe, halt5. If no process can terminate,
    report unsafe, halt6. Go to step 1

94
Safe and Unsafe states
  • Safe stated
  • Not deadlocked
  • There is a way to satisfy all possible future
    requests

(a)
(b)
(c)
  • Fig. 6-9. Three resource allocation states (a)
    Safe. (b) Safe. (c) Unsafe.

95
deadlock detection - 4 resource-types
  • Resources - (Tape-drives Modems Printers
    CD-ROMs)
  • Existing resources - E (4 2 3 1)
  • Available resources - A (2 1 0 0)
  • Current allocation
  • Request matrix

0
0
0
1
0
0
1
2
0
1
2
0
2
1
0
0
1
1
0
0
2
1
0
0
96
Safety of states with multiple resources
  • Granting a printer to B leads to a safe state
  • Now, granting the last printer to E leads to
    deadlock

97
Multiple resources of each kind
  • Assume n processes and m resource classes
  • Use four arrays
  • Current allocation matrix Cn x m
  • Request matrix Rn x m
  • Existing resources vector Em
  • Available resources vector Am
  • Detect deadlocks by comparing vectors
  • for 1 j m Cij Aj Ej
  • A B if for 0 i m Ai
    Bi

98
Bankers Algorithm (multiple resources)
  • Look for a row R whose unmet resource needs are
    all smaller then or equal to A. If no such row
    exists, the system will eventually deadlock.
  • Assume the process of the row chosen finishes
    (which is possible). Mark that process as
    terminated and add all its resources to the A
    vector
  • Repeat steps 1 and 2 until either all processes
    are marked terminated, which means safe, or until
    a deadlock occurs, which means unsafe.

99
Checking safety - example
  • Process Allocation Max Available
  • A B C A B C A B C
  • P0 0 1 0 7 5 3 3
    3 2
  • P1 2 0 0 3 2 2
  • P2 3 0 2 9 0 2
    E
  • P3 2 1 1 2 2 2
  • P4 0 0 2 4 3 3 10
    5 7
  • The Need matrix will be
  • P0 7 4 3 ? ltP1 P3 P4 P2 P0 gt is
    Safe
  • P1 1 2 2
  • P2 6 0 0
  • P3 0 1 1
  • P4 4 3 1

100
one-more-request - example
  • Suppose P1 requests now (1, 0, 2) - Request lt
    Available
  • To execute the safety algorithm we note that if
    granted we will have now for P1
  • Allocation 3 0 2 Needed 0 2 0
  • and a safe path ltP1 P3 P4 P0 P2 gt
  • However, a request for 0 2 0 by P0 is not
    safe
  • it is available
  • But, none of the Needed tuples in the resulting
    state is smaller than the Available tuple

101
Deadlock Avoidance is not practical
  • Maximum resource request per process is not known
    initially
  • moreover, its point in time is also unknown
  • Resources may disappear
  • some devices leave the available pool (break
    down)
  • New processes may appear
  • the system is dynamic and processes are born and
    die at any moment

102
Deadlock Detection and Recovery
  • Find if a deadlock exists
  • if there is, which processes and resources
  • Detection detect cycles in resource graph
  • Algorithm DFS node and arc marking

103
Find cycles
  • For each node, N, in the graph, perform the
    following 5 steps with N as starting node
  • 1. Initialize L to the empty list and designate
    all arcs as unmarked
  • 2. Add the current node to the end of L and check
    if the node appears twice in L. If it does, the
    graph contains a cycle, terminate.
  • 3. If there are any unmarked arcs from the given
    node, go to 4., if not go to 5.
  • 4. Pick any unmarked outgoing arc and mark it.
    Follow it to the new current node and go to 2.
  • 5. We have reached a deadend. Go back to the
    previous node, make it the current node and go to
    2. If the node is the initial node, there are no
    cycles in the graph, terminate

104
Detection - extract a cycle
  • 1. Process A holds R and requests S
  • 2. Process B holds nothing and requests T
  • 3. Process C holds nothing and requests S
  • 4. Process D holds U and requests S and T
  • 5. Process E holds T and requests V
  • 6. Process F holds W and requests S
  • 7. Process G holds V and requests U

105
When should the system check for deadlock ?
  • For every request instance - too expensive
  • every k minutes...
  • whenever cpu utilization drops strongly (good
    sign of deadlock..)At least two processes in
    H,W

106
Recovery
  • Preemption - possible in some rare cases
  • temporarily take a resource away from its current
    owner
  • Rollback - possible with checkpointing
  • keep former states of processes (checkpoints) to
    enable release of resources and going back
  • Killing a process - easy way out, may cause
    problems in some cases, depending on process
    being rerunable
  • Bottom line hard to recover from deadlock,
    avoid it

107
Example - deadlocks in DBMSs
  • For database records that need locking first and
    then updating
  • Deadlocks occur frequently because records are
    dynamically requested by competing processes
  • DBMSs, therefore, need to employ deadlock
    detection and recovery procedures
  • Recovery is possible - transactions are
    checkpointed - release everything and restart
  • Not useful for network messages sent and
    received, for example - cannot be terminated and
    started over safely

108
Factors Determining Process to Kill
  • What the priority of the process is
  • How long the process has computed, and how much
    longer the program will compute before completing
    its designated task
  • How many and what type of resources the process
    has used (for example, whether the resources are
    simple or preempt)
  • How many more resources the process needs in
    order to complete
  • How many processes will need to be terminated
  • Whether the process is interactive or batch

109
Deadlock handling combined approach
  • allocation (and deadlocks) are all around -
    different strategies can be used for different
    classes of resources
  • Simplistic example - four classes
  • Internal resources used by the system PCB
  • Central memory for users processes
  • Assignable devices Tape drives, etc.
  • Swap space on disk for user processes

110
Combined approach (cntd.)
  • Internal Resources use Prevention through
    resource ordering, no selection among pending
    processes
  • Central memory use prevention through
    Preemption, a process can always be swapped-out
  • Assignable devices if device-requirement
    information is available, use Avoidance
  • Swap space use Preallocation, since maximal
    storage requirements are known in advance

111
Additional issues of deadlock
  • Deadlocks may occur with respect to actions of
    processes, not resources - waiting for semaphores
  • Starvation can result from a bad allocation
    policy (such as smallest-file-first, for
    printing) and for the starved process will be
    equivalent to a deadlock (cannot finish running)
  • Summary of deadlock treatment
  • Ignore problem
  • Detect and recover
  • Avoid (be only in safe states)
  • Prevent by using an allocation policy or
    conditions

112
The Situation in Practice
  • Most OSs in use, and especially NT, Solaris ,
    ignore deadlock or do not detect it
  • Tools to kill processes but usually without loss
    of data
  • In Windows NT there is system call
    WaitForMultipleObjects that request all resources
    at once
  • System provides all resources, if free
  • There is no lock of resources if only few are
    free
  • Prevents Hold Wait, but difficult to implement!
Write a Comment
User Comments (0)
About PowerShow.com