CS 149: Operating Systems February 19 Class Meeting Department of Computer Science San Jose State University Spring 2015 Instructor: Ron Mak
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 2 Dining Philosophers Problem Five philosophers are seated at a round table. Each philosopher has a plate of spaghetti. There is a single fork between each plate. A philosopher alternates between thinking and eating. In order to eat spaghetti, a philosopher must obtain both the left and the right fork.
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 3 Dining Philosophers Problem, cont’d Lunchtime in SJSU’s Department of Philosophy. Operating Systems: Design and Implementation Tanenbaum & Woodhull (c) 2006 Prentice-Hall, Inc. All rights reserved
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 4 Dining Philosophers Problem: Another Solution Use an array of semaphores, one semaphore per philosopher. A hungry philosopher can block if the needed forks are unavailable. Use a shared array to keep track of each philosopher’s state: THINKING HUNGRY (wants to get forks) EATING Use a mutex to protect the shared state array.
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 5 Dining Philosophers Problem: Another Solution Use a mutex to protect the shared state array. Don’t allow a philosopher to enter its EATING state if either of his neighbors is eating.
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 6 Dining Philosophers: Another Solution, cont’d Operating Systems: Design and Implementation Tanenbaum & Woodhull (c) 2006 Prentice-Hall, Inc. All rights reserved
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 7 lock(&mutex); unlock(&mutex); wait(&s[i]); When and how is a philosopher ever unblocked? Dining Philosophers: Another Solution, cont’d Operating Systems: Design and Implementation Tanenbaum & Woodhull (c) 2006 Prentice-Hall, Inc. All rights reserved
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 8 lock(&mutex); unlock(&mutex); signal(&s[i]); Dining Philosophers: Another Solution, cont’d Operating Systems: Design and Implementation Tanenbaum & Woodhull (c) 2006 Prentice-Hall, Inc. All rights reserved
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 9 Monitors Monitors are a new language feature to support concurrent programming. A monitor is an abstract data type (ADT). It has a set of operations that support mutual exclusion and process sequencing. But the programmer who uses the monitor doesn’t need to know (or care) how these operations are implemented.
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 10 Monitors, cont’d A monitor (like any other class) has one or more methods. You instantiate a monitor to get a monitor object. Only one process at a time can be executing any one of a monitor object’s methods. Therefore, each monitor method is by default a critical region that supports mutual exclusion.
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 11 Monitors, cont’d To support process sequencing, a monitor has condition variables. Call wait() and signal() on a condition variable. Condition variables are similar to semaphores.
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 12 Java Monitors The Java programming language supports the concept of monitors. Define a class, as usual. You can even name the class Monitor. Not necessary, of course. Create objects of the class as usual.
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 13 Java Monitors, cont’d Mark methods of the class as synchronized. At run time, only one process or thread can be executing any synchronized method of the monitor object. Therefore, each synchronized method is a critical region. No explicit mutexes are necessary.
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 14 Java Monitors, cont’d Each Java object has one built-in condition variable. Use the Thread class methods wait() and notifyAll(). notifyAll() is equivalent to signal().
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 15 Dining Philosophers: Java Solution public class DiningPhilosophers { static Philosopher philosophers[]; // philosopher threads static ForkMonitor monitor; public static void main(String args[]) throws Exception {... philosophers = new Philosopher[philosopherCount]; monitor = new ForkMonitor(philosophers); for (int i = 0; i < philosopherCount; i++) { philosophers[i] = new Philosopher(i, monitor); }... for (int i = 0; i < philosopherCount; i++) { philosophers[i].start(); }... } } philosopherCount is a command-line argument. Create the philosopher theads. Start the philosopher theads.
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 16 Dining Philosophers: Java Solution, cont’d public class DiningPhilosophers {... public static void main(String args[]) throws Exception {... try { Thread.sleep(1000*seconds); } catch(InterruptedException ex) {} for (int i = 0; i < philosopherCount; i++) { philosophers[i].timesUp(); philosophers[i].join(); } for (int i = 0; i < philosopherCount; i++) { System.out.printf("%-12d", philosophers[i].eaten()); } System.out.println(); } } seconds is a command-line argument. Sleep while the philosopher theads are running. Kill the philosopher theads. Print how many times each philosopher ate.
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 17 Dining Philosophers: Java Solution, cont’d public class Philosopher extends Thread { private int id; private State state; private int timesEaten; private boolean eatThink; private ForkMonitor monitor; private Random generator = new Random(); public enum State {THINKING, WAIT_LEFT, WAIT_RIGHT, EATING}; public Philosopher(int id, ForkMonitor monitor) { this.id = id; this.state = State.THINKING; this.timesEaten = 0; this.eatThink = true; this.monitor = monitor; }... } What states that a philosopher can be in.
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 18 Dining Philosophers: Java Solution, cont’d public class Philosopher extends Thread {... public int id() { return this.id; } public int eaten() { return this.timesEaten; } public State state() { return this.state; } public void changeState(State state) { this.state = state; DiningPhilosophers.print(); } public void ateAgain() { ++timesEaten; } public void timesUp() { eatThink = false; }... }
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 19 Dining Philosophers: Java Solution, cont’d public class Philosopher extends Thread {... public void run() { snooze(); while (eatThink) { try { monitor.getForks(id); snooze(); monitor.releaseForks(this.id()); snooze(); } catch (Exception ex) { ex.printStackTrace(); } } }... } When started, every thread runs this method. Time to get seated at the table. Eat and think until it’s time to go home. Get forks and eat for a while. Release forks and think for a while.
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 20 Dining Philosophers: Java Solution, cont’d public class ForkMonitor { private boolean forks[]; private Philosopher philosophers[]; public ForkMonitor(Philosopher philosophers[]) { forks = new boolean[philosophers.length]; for (int i = 0; i < forks.length; i++) { forks[i] = true; } this.philosophers = philosophers; }... } All forks are initially available.
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 21 Dining Philosophers: Java Solution, cont’d public class ForkMonitor { private boolean forks[]; private Philosopher philosophers[];... public synchronized void getForks(int id) throws Exception { int left = id; // left fork index int right = (id + 1)%forks.length; // right fork index while (!forks[left] || !forks[right]) { philosophers[id].changeState(!forks[left] ? Philosopher.State.WAIT_LEFT : Philosopher.State.WAIT_RIGHT); wait(); } forks[left] = false; forks[right] = false; philosophers[id].changeState(State.EATING); philosophers[id].ateAgain(); }... } Only one philosopher can be getting forks at a time. Try to get both left and right forks. Take forks and start eating. Wait for both forks to become available.
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 22 Dining Philosophers: Java Solution, cont’d public class ForkMonitor { private boolean forks[]; private Philosopher philosophers[];... public synchronized void releaseForks(int id) throws Exception { int left = id; // left fork index int right = (id + 1)%forks.length; // right fork index forks[left] = true; forks[right] = true; philosophers[id].changeState(State.THINKING); notifyAll(); } } Demo Only one philosopher can be releasing forks at a time. Release forks and resume thinking. Notify any waiting philosophers that forks are now available.
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 23 Deadlocks Deadlocks, AKA the Deadly Embrace In either case, your application is hung. What happened? Deadlocks can occur when a set of processes are contending for resources. The sequence of events required for a process to use a resource : 1. Request the resource. 2. Use the resource. 3. Release the resource.
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 24 Deadlocks, cont’d Deadlocks can occur when the OS grants processes exclusive access to resources. Hardware devices (e.g., DVD reader) Memory Data A resource is anything that can be used by only a single process at a time. A process may need to have exclusive access to several resources at a time. Resources are preemptable and non-preemptable.
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 25 Deadlocks over Resources Preemptable resource Can be taken away from a process that owns it. No ill effects on the process. Examples: memory, CPU Non-preemptable resource Cannot be taken away from the process owning it without causing the process to fail. Example: CD recorder
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 26 Deadlocks over Resources, cont’d If a process requests a resource that is not available, then the process must wait. The OS may unblock the process when the resource becomes available again.
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 27 Deadlock Definition A set of processes is deadlocked if: Each process in the set is waiting for an event. Only another process in the set can cause the event. If all the processes are waiting, none of them can cause the event that wakes up the blocked processes.
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 28 Deadlock Conditions Mutual exclusion Each resource is either available or currently assigned to exactly one process. Hold and wait Processes currently holding resources that were granted earlier can request new resources.
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 29 Deadlock Conditions, cont’d No preemption A resource previously granted to a process cannot be forcibly taken away from the process. The process must explicitly release the resource. Circular wait A circular chain of processes each waiting for a resource held by another process in the chain.
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 30 Deadlock Modeling Resource allocation graphs Two types of nodes: processes (shown as circles) and resources (shown as squares). (a) Process A holds resource R. (b) Process B requests resource S. (c) A deadlock situation. Modern Operating Systems, 3 rd ed. Andrew Tanenbaum (c) 2008 Prentice-Hall, Inc All rights reserved
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 31 Deadlock Modeling, cont’d Process C waits for Resource T, which is held by Process D. Process D waits for Resource U, which is held by Process C. Deadlock cycle: C T D U C Modern Operating Systems, 3 rd ed. Andrew Tanenbaum (c) 2008 Prentice-Hall, Inc All rights reserved
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 32 Deadlock Modeling, cont’d Suppose we have three processes A, B, and C that are competing for resources R, S, and T. Their requests and releases: The process scheduler is free to run any unblocked process at any instant.
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 33 Deadlock Modeling, cont’d One solution: The scheduler allows Process A to run to completion, then Process B, and finally Process C. No competition for resources no deadlocks. But also no parallelism.
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 34 Deadlock Modeling, cont’d What happens if we use the Round-Robin instead? A blocksB blocks C blocks Modern Operating Systems, 3 rd ed. Andrew Tanenbaum (c) 2008 Prentice-Hall, Inc All rights reserved
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 35 Deadlock Modeling, cont’d Would a different scheduling order help? Process B is suspended. What happens now if Process B wakes up? Modern Operating Systems, 3 rd ed. Andrew Tanenbaum (c) 2008 Prentice-Hall, Inc All rights reserved
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 36 Pthreads Deadlock Example int worker1_id; int worker2_id; void *worker1(void *param); void *worker2(void *param); pthread_mutex_t mtx1; pthread_mutex_t mtx2; int main(int argc, char *argv[]) { srand(time(0)); pthread_mutex_init(&mtx1, NULL); pthread_mutex_init(&mtx2, NULL);... } Where is there a potential deadlock lurking in this code?
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 37 Pthreads Deadlock Example, cont’d... int main(int argc, char *argv[]) {... printf("main: Create worker 1 thread.\n"); worker1_id = 1; pthread_t worker1_tid; pthread_attr_t worker1_attr; pthread_attr_init(&worker1_attr); pthread_create(&worker1_tid, &worker1_attr, worker1, &worker1_id); printf("main: Create worker 2 thread.\n"); worker2_id = 2; pthread_t worker2_tid; pthread_attr_t worker2_attr; pthread_attr_init(&worker2_attr); pthread_create(&worker2_tid, &worker2_attr, worker2, &worker2_id); printf("main: Wait for workers to finish.\n"); pthread_join(worker1_tid, NULL); pthread_join(worker2_tid, NULL); printf("main: Done!\n"); }
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 38 Pthreads Deadlock Example, cont’d void *worker1(void *param) { printf("Worker1: Locking mutex 1.\n"); pthread_mutex_lock(&mtx1); sleep(rand()%3); printf("Worker1: Locking mutex 2.\n"); pthread_mutex_lock(&mtx2); printf("Worker1: Working.\n"); sleep(rand()%5); printf("Worker1: Unlocking mutex 2.\n"); pthread_mutex_unlock(&mtx2); sleep(rand()%3); printf("Worker1: Unlocking mutex 1.\n"); pthread_mutex_unlock(&mtx1); }
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 39 Pthreads Deadlock Example, cont’d void *worker2(void *param) { printf("Worker2: Locking mutex 2.\n"); pthread_mutex_lock(&mtx2); sleep(rand()%3); printf("Worker2: Locking mutex 1.\n"); pthread_mutex_lock(&mtx1); printf("Worker2: Working.\n"); sleep(rand()%5); printf("Worker2: Unlocking mutex 1.\n"); pthread_mutex_unlock(&mtx1); sleep(rand()%3); printf("Worker2: Unlocking mutex 2.\n"); pthread_mutex_unlock(&mtx2); } Demo
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 40 Deadlock Strategies 1. Ignore the problem altogether. 2. Detection and recovery. 3. Avoidance by careful resource allocation. 4. Prevention by negating one of the four necessary conditions. Mutual exclusion Hold and wait No preemption Circular wait
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 41 Ignore Deadlocks Deadlocks may be unavoidable when there are limited resources. The OS can impose draconian measures to prevent deadlocks that happen only occasionally. If there are too many restrictions on the use of resources, the cost in inconvenience is too high. Users may rather tolerate infrequent system lockups.
Computer Science Dept. Spring 2015: February 19 CS 149: Operating Systems © R. Mak 42 Deadlock Detection and Recovery The OS monitors resource requests and releases. It maintains an internal resource allocation graph. If it detects any cycles, it starts to kill processes one by one until the cycle is broken. The OS periodically checks to see if any processes have been continuously blocked for a long time. Kill off such processes.