CS 5460: Operating Systems
CS5460: Operating Systems
Lecture 11: Deadlock
(Chapter 7)
CS5460: Operating Systems Lecture 11: Deadlock (Chapter 7) CS - - PowerPoint PPT Presentation
CS5460: Operating Systems Lecture 11: Deadlock (Chapter 7) CS 5460: Operating Systems Dining Philosophers Problem Five Philosophers sitting around a table One fork between each pair of philosophers Rule: Need two forks to eat
CS 5460: Operating Systems
(Chapter 7)
CS 5460: Operating Systems
Five Philosophers sitting around a table One fork between each pair of philosophers Rule: Need two forks to eat Rule: Can only acquire one fork at a time Rule: Once fork acquired, not relinquished until done When done eating, relinquish both forks
CS 5460: Operating Systems
Class Philosophers { private: semaphore fork[5]; public: void Eat(int id); } Philosophers::Eat( int mypid ) { entry: // Acquire “my” forks EAT: // Eat spaghetti exit: // Relinquish “my” forks }
Let’s solve this interactively…
– Hint: Use provided semaphores – Avoid deadlock – Avoid unfairness – Does order or fork acquisition matter?
CS 5460: Operating Systems
Class Philosophers { private: semaphore fork[5]; public: void Eat(int id); } Philosophers::Eat( int mypid ) { entry: // Acquire “my” forks P( fork[mypid] ); P( fork[(mypid+1)%5] ); EAT: // Eat spaghetti exit: // Relinquish “my” forks V( fork[mypid+1]%5 ); V( fork[mypid] ); }
Let’s solve this interactively
– Hint: Use provided semaphores – Does order matter?
CS 5460: Operating Systems
Class Philosophers { private: semaphore fork[5]; public: void Eat(int id); } Philosophers::Eat( int mypid ) { entry: // Acquire “my” forks P( fork[mypid] ); P( fork[(mypid+1)%5] ); EAT: // Eat spaghetti exit: // Relinquish “my” forks V( fork[mypid+1]%5 ); V( fork[mypid] ); }
Let’s solve this interactively
– Hint: Use provided semaphores – Does order matter?
» Yes!
CS 5460: Operating Systems
Class Philosophers { private: semaphore fork[5]; public: void Eat(int id); } Philosophers::Eat( int mypid ) { entry: if (mypid==0) return; P( fork[mypid] ); P( fork[(mypid+1)%5] ); EAT: // Eat spaghetti exit: V( fork[mypid+1]%5 ); V( fork[mypid] ); }
Let’s solve this interactively
– Hint: Use provided semaphores – Does this solve the deadlock problem? – Does it work overall?
CS 5460: Operating Systems
Class Philosophers { private: semaphore fork[5]; public: void Eat(int id); } Philosophers::Eat( int mypid ) { entry: if (mypid&1) { P( fork[mypid] ); P( fork[(mypid+1)%5] ); } else { P( fork[(mypid+1)%5] ); P( fork[mypid] ); } EAT: // Eat spaghetti exit: V( fork[mypid+1]%5 ); V( fork[mypid] ); }
Let’s solve this interactively
– Hint: Use provided semaphores – Does this solve problem?
» Yes… why?
– Does order of release matter?
CS 5460: Operating Systems
CS 5460: Operating Systems
Deadlock: Two or more threads are waiting on
events that only those threads can generate
– Computers don’t see the “big picture” needed to break the stalemate – Hard to handle automatically à à lots of theory, little practice Livelock: Thread blocked indefinitely by other
thread(s) using a resource
Livelock naturally goes away when system load
decreases
Deadlock does not go away by itself
CS 5460: Operating Systems
CS 5460: Operating Systems
Mutual exclusion: Resources cannot be shared Hold and wait: A thread is both holding a resource
and waiting on another resource to become free
No preemption: Once a thread gets a resource, it
cannot be taken away
Circular wait: There is a cycle in the graph of who
has what and who wants what…
Thread_A: Thread_B: P(X); P(Y); P(Y); P(X); A B X Y
CS 5460: Operating Systems
What is smallest number of threads needed to
deadlock?
CS 5460: Operating Systems
Class Philosophers { private: semaphore fork[5]; public: void Eat(int id); } Philosophers::Eat( int mypid ) { entry: if (mypid&1) { P( fork[mypid] ); P( fork[(mypid+1)%5] ); } else { P( fork[(mypid+1)%5] ); P( fork[mypid] ); } < Eat spaghetti > exit: V( fork[mypid+1]%5 ); V( fork[mypid] ); }
Removing deadlock…
– Which condition did we eliminate in V2.0 solution? – How?
CS 5460: Operating Systems
Deadlock ignorance – Why worry? Deadlock detection – Figure out when deadlock has occurred and “deal with it”
» Figuring it out à à mildly difficult » Dealing with it à à often messy, may need to reboot
Deadlock avoidance – Reject resource requests that might lead to deadlock Deadlock prevention – Use “rules” that make it impossible for all four conditions to hold
CS 5460: Operating Systems
Resource allocation graph
– Resources {r1, …, rm} – Threads {t1, …, tm} – Edges:
» ti à à rj: ti wants rj » rj à à ti: rj allocated to ti
Acyclic à
à no deadlocks
Cyclic à
à deadlock
Cycle detection
– Several known algorithms – O(n2), n = |T| + |R|
Alternative approach: Wait for someone to hold a resource for
way to long, then decide that deadlock has occurred
t1 t2 t3 t4 r2 r5 r4 r3 r1
CS 5460: Operating Systems
Periodically scan for deadlocks When to scan:
– Just before granting resources? – Whenever resources unavailable? – Fixed intervals? – When CPU utilization drops? – When thread not runnable for extended period of time?
How to recover?
– Terminate threads – Break locks – Invoke exception handlers – Create more resources – Reboot – …
CS 5460: Operating Systems
Idea: – Run version of deadlock detection algorithm in resource allocator – Add “claim” edges to resources threads may request – A cycle in extended graph à à unsafe state à à may lead to deadlock – Deny allocations that result in unsafe states
» Claim edge converted to request edge » Thread blocks until request can be safely satisfied t1 t2 t3 t4 r2 r5 r4 r3 r1 Do you think this is used often? Why or why not?
CS 5460: Operating Systems
Prevent deadlock by ensuring at least one
necessary condition cannot occur:
– Mutual exclusion: Make resources shared (hard in practice) – Hold and wait: Several possibilities…
» Never require more than one resource at a time » Require all resources to be acquired at once » Require current resources to be freed and reacquired if need more
– No preemption: Make resources preemptible
» Resource allocator releases held resources when new request arrives » Threads must be coded to expect this behavior
– Circular wait
» Strictly order resources à à must acquire in increasing order » Requires global system knowledge
We’ve been talking about deadlocked threads /
processes on a single machine
Of course, deadlock can also occur across
machines
Distributed deadlock can be hard to deal with – Hard to get a good picture of the global system – May be hard to take coordinated action – Distributed systems are often in a state of partial failure
CS 5460: Operating Systems
Any time you write code that acquires more than
CS 5460: Operating Systems
User mode code on Linux – Helgrind – a Valgrind plugin that dynamically checks for circular wait Linux kernel – Lock validator – dynamically checks for circular wait Solaris kernel – Has a strict lock ordering – “Lock lint” tool performs static analysis Windows thread pool – Create more threads if stuck Linux CPU scheduler – Avoid starving any thread
CS 5460: Operating Systems
CS 5460: Operating Systems
Four conditions required for deadlock to occur: – Mutual exclusion – Hold and wait – No resource pre-emption – Circular wait Four techniques for handling deadlock – Prevention: Design rules so one condition cannot occur – Avoidance: Dynamically deny “unsafe” requests – Detection and recovery: Let it happen, notice it, and fix it – Ignore: Do nothing, hope it does not happen, reboot often
CS 5460: Operating Systems