Process Synchronization - PowerPoint PPT Presentation

1 / 89
About This Presentation
Title:

Process Synchronization

Description:

{ int value, flag; // flag is a variable for test&set - true when 0. list_proc L; ... S.flag = 0; 8/10/09. Amnon Meisels OS_00 Ch 3. 26. Atomicity of Semaphores ... – PowerPoint PPT presentation

Number of Views:53
Avg rating:3.0/5.0
Slides: 90
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
Mutual Exclusion - attempts...
  • 1. Disable interrupts
  • Violates condition 3
  • 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

5
.. 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()

6
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 /

7
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

8
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

9
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

10
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

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

12
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

13
1st assignment - suspend()
  • A thread wants to read messages -
  • loop
  • enter() critical section and check mailbox
  • if mailbox empty - leave(), suspend()
  • otherwise, read mail item and leave()
  • end loop
  • The Mailer wants to add message -
  • enter() critical section
  • add message (if needed wakeup suspended
    thread)
  • leave()
  • enter() and leave() will block the thread, if
    needed

14
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...

15
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

16
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 up
  • Each process calls wakeup(other) when leaving the
    critical section...

17
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

18
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)

19
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

20
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 ? /

21
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 /

22
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

23
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

24
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)

25
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

26
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

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 blocks on an empty
    mailbox and mailboxes have to be protected for
    read/write
  • two semaphores rw for read/write et for
    empty
  • thread mailer
  • down(et) down(rw)
  • down(rw) add_message
  • read_message up(et)
  • up(rw) up(rw)
  • .. ...

30
Bounded-buffer for sent messages
  • Threads use the system call send() to send
    messages, which are then stored in a large buffer
    for the mailer to deliver to threads mailboxes
  • The buffer is bounded and so send() is a
    producer and the inner function of the Mailer
    that extracts the messages and delivers them to
    their destination is a consumer
  • These two functions must use two common
    semaphores to implement a synchronized
    bounded-buffer and initialize one of the
    semaphores to the (user defined) size of the
    buffer N

31
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

32
More on Synchronization...
  • Three processes p1 p2 p3
  • semaphores s1, s2
  • 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)

33
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

34
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 /

35
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)

36
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)

37
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

38
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

39
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

40
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
  • Problems...
  • 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 ?

41
Implementing Monitors with Semaphores
  • 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 /

42
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

43
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 /

44
Message passing (contnd.)
  • 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)

45
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

46
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_recieve_from
  • This enables an up operation 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

47
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

48
Equivalence Semaphores with Message passing
  • use a semaphore-process (mailbox) p
  • p keeps the counter of the semaphore s
  • down(s) - send(p,down(s))
  • receive(p,ack)
  • if s lt 0 p does not send an acknowledgement
  • up(s) - send(p,up(s))
  • if s lt 0 p sends the acknowledgement to a
    selected process

49
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)

50
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.

51
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)

52
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)

53
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

54
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

55
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)

56
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...

57
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)

58
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

59
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

60
..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 wait for customers
    customers wait for barbers count queue length..

61
..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()

62
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 /

63
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

64
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
  • Block process while waiting for Resources

65
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

66
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
67
the occurance of deadlocks
68
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

69
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)

70
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

71
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)

72
Safe and Unsafe states - 1 resource
  • safe states
  • Not deadlocked
  • There is a way to satisfy all possible future
    requests

73
Bankers Algorithm (single resource)
  • Simulate allocation of resources
  • Bankers Algorithm (Dijkstra 1965)
  • 1. Pick a process that can terminate (enough free
    resources)
  • 2. Free all its resources (simulation)
  • 3. Mark process terminated
  • 4. If all processes marked, report safe, halt
  • 5. If no process can terminate, report unsafe,
    halt
  • 6. Go to step 1.

74
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

75
Bankers Algorithm (multiple resources)
  • 1. Look for process Pi for which the row i of R
    is less than A (process can proceed).
  • 2. If found, add row i of C (i.e. all its
    resources) to A, mark Pi, and go to step 1.,
    else terminate.
  • 3. Repeat steps 1 and 2 until either all
    processes are marked terminated, which means
    safe, or until a deadlock occurs, which means
    unsafe.

76
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

77
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

78
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

79
A Resource Allocation Graph
80
Resource Allocation Graph With A Deadlock
81
A Cycle But No Deadlock
82
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.

83
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
84
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..)

85
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

86
Eaxmple - 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

87
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
  • Avoid (be only in safe states)
  • Detect and recover
  • Prevent by using an allocation policy or
    conditions
  • Ignore problem

88
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

89
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
Write a Comment
User Comments (0)
About PowerShow.com