CS162 Lecture - 2/18/09 Deadlock - Resources - ranges from CPU time to disk space to channel I/O time Resources fall into 2 categories - Preemptible - Can take the resource away, use it for something else, and then give it back. Examples include the processor, I/O channels, main memory, etc. Non-preemptible - Once the resource is given, it can't be given back until the process is done with it. Examples include file space, terminal printers, semaphores, etc. OS makes 2 kinds of resource decisions - Allocation - for non-preemptible resources Scheduling - for preemptible resources Systems have resources. A typical process loop is: request a resource, use it, then free it Deadlock traffic jam analogy (no one can move): Cars entering here | | | | | | | | | | | | | ---+ +-------+ | +--- +-------------+ ---+ | +-------+ | +--- | | | | | | | | | | | | | | | | | | | | | | | | ---+ | +-------+ | +--- +-------------+ ---+ +-------+ +--- | | | | | | | | Deadlock example with semaphores: Process 1: Process 2: P(X) P(Y) P(Y) P(X) (X and Y are the semaphore resources) Deadlock has a lot of theory but is ignored in practice, because the solutions are too expensive or you have to know the future. Deadlock definition - a siutation where each set of processes is waiting for something from other processes in the set. Since all are waiting, none can provide any of the things being waited for. In general, there are 4 conditions for deadlock - 1) Mutual exclusion - two or more resources cannot be shared (i.e. optical disk drives, printers, etc) 2) Hold and wait processes - gets resources and waits for more 3) No preemption - once allocated, a resource cannot be taken away 4) There is circularity in the graph of who has what and who wants what, i.e. Processes A, B, C Resources X, Y, Z A has X and wants Y, B has Y and wants Z, C has Z and wants X Approaches to dealing with deadlock - 1) Prevention - organize the system so deadlock is impossible (may make the system inefficient) - Eliminate 1 of the 4 necessary deadlock conditions - Create enough resources so there's always enough (might not be possible) - Make all resources shareable (some resources can't be shared, i.e. a printer) - Don't permit mutual exclusion (not feasible) - Virtualize non-shared resources (i.e. use spooling for printer) - Use only uniprogramming - Don't allow waiting and holding - process must crash if resources isn't available right away (phone company does this - if you can't connect then your call is dropped) - Process must request all resources at once (requires sufficient knowledge - isn't very feasible) - Will probably request too much just to be safe - Starvation is possible - may way indefinitely long until everything is free - Isn't possible sometimes - Process must release all resources before requesting new ones - awkward solution, often won't work - Make ordered/heirarchichal requests - ask for all R1's, R2's, etc. all processes follow the same ordering scheme. This prevents a circular deadlock but requires you to know in advance which resources you'll need - We can avoid deadlock if resource allocations are "safe" - A safe state is one in which deadlock is not inevitible (there exists a sequence of task completions which leads to all tasks being completed) - A safe allocation is one that leads to a safe state - A safe sequence is the sequence of task completions leading from a safe state to another safe state. A complete safe sequence leads to all tasks being completed - An unsafe state will always go into deadlock - Bankers Algorithm - Used to compute a safe state - Process Has Needs A 90 100 B 50 110 C 30 160 Bank has 20 available. - For each process J, we need to know 1) max(J, k) which is the max number of k that will be requested by J 2) allocation(J, k) which is the number of k currently held by J 3) need(J, k) which is max(J, k) - allocation(J, k) - For every resource k we need to know available(k) which is the number still available Algorithm: a. given a request, let alloc*(J, k) and avail*(k) be the state after the request is granted b. if all processes can finish with no additional resources, then there's no deadlock (safe state) c. find a process X for which for all k, need*(X, k) <= avail*(k). If there is no such X, we have an unsafe state. Otherwise, "mark" process finished d. if all processes are marked as finished, or can finish with no additional resources, then we don't have deadlock (safe state) e. for all k, let avail(j) = avail*(k) + alloc*(X, k). f. go to c - Banker's algorithm only possible if we have knowledge of max resources in advance, and it is extremely costly to run it, so it is not used in practice 2) Cure - determine deadlock and take drastic action (i.e. kill a process, free a resource, etc) - Check if deadlock exists (look for circles in the resource graph) - Run this check 1) periodically 2) when system seems slow 3) when processes have been waiting a long time 4) when there are many processes and CPU is idle - 2 general approaches - kill all deadlocked processes - kill one processes at a time until deadlock circuit is broken (this is preferable) - want to select minimum cost process to kill Rollback - causing the process to return to an earlier checkpoint Checkpoint - a copy of the state of the process at some past time - In general, prevention of deadlock is expensive and/or inefficient. Detection is also expensive and recovery is seldom possible. - Some real-world solutions: - IBM OS/360 - data set names are enqueued all at once on a job basis - devices, volumes, and memory allocated in order on a per-job-step basis - temporary file system can cause deadlocks - operator intervenes and kills job - Multics: - in main path of process, must request resources in specific order - in secondary paths (which can be preempted), must release resources held out of order - MTS: - put in mild constraints on resource allocation - ran deadlock detection algorithm periodically - Unix: - complicated