1 / 25

CS444/CS544 Operating Systems

CS444/CS544 Operating Systems. Classic Synchronization Problems 2/28/2007 Prof. Searleman jets@clarkson.edu. Outline. Classic Synchronization Problems Dining Philosophers Deadlock, revisited Synchronization with Message Passing Events & Condition Variables NOTE: Read: Chapter 7

huela
Download Presentation

CS444/CS544 Operating Systems

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. CS444/CS544Operating Systems Classic Synchronization Problems 2/28/2007 Prof. Searleman jets@clarkson.edu

  2. Outline • Classic Synchronization Problems • Dining Philosophers • Deadlock, revisited • Synchronization with Message Passing • Events & Condition Variables NOTE: • Read: Chapter 7 • Exam#2 – Tues. 3/13, 7:00 pm, SC160 • K-12 TA interest meeting: 3/7, 4:00, Barben A • both undergrad & graduate TA’s available

  3. Classical Synchronization Problems • Bounded-Buffer Problem (also called Producer-Consumer) one-way communication with limited resources • Dining-Philosophers Problem shared resources • Readers and Writers Problemshared database

  4. Dining-Philosophers Problem #define N NUM_PHILOSOPHERS #define RIGHT i #define LEFT (i+1)%N semaphore_t chopstick[N]; void init(){ for (i=0; i<N; i++) chopstick[i].value = 1; }

  5. Semaphore “Solution” to Dining Philosophers void philosophersLife(int i){ while (1) { think(); wait(chopstick[RIGHT]); grab_chopstick(RIGHT); wait(chopstick[LEFT]); grab_chopstick(LEFT); eat(); putdownChopsticks(); signal(chopstick[RIGHT]); signal(chopstick[LEFT]); } } Problem? p0 gets chopstick 0 p1 gets chopstick 1 … pN-1 gets chopstick N-1 Deadlock potential! Solution?

  6. Deadlock • Deadlock exists in a set of processes/threads when all processes/threads in the set are waiting for an event that can only be caused by another process in the set (which is also waiting!). • Dining Philosophers is a perfect example. Each holds one chopstick and will wait forever for the other.

  7. Resource Allocation Graph • Deadlock can be described through a resource allocation graph • Each node in graph represents a process/thread or a resource • An edge from node P to R indicates that process P had requested resource R • An edge from node R to node P indicates that process P holds resource R • If graph has cycle, deadlock may exist. If graph has no cycle, deadlock cannot exist.

  8. Philosopher 1 has chopstick 1 and wants chopstick 2 Philosopher 1 P1 blocked Philosopher 2 has chopstick 2 and wants chopstick 3 Chopstick 2 Chopstick 1 P0 blocked Philosopher 2 Philosopher 0 Philosopher 0 has chopstick 0 and wants chopstick 1 Chopstick 3 Chopstick 0 Philosopher 3 P3 blocked Philosopher 3 has chopstick 3 and wants chopstick 0 Cycle in Resource Allocation Graph wait(chopstick[i]); wait(chopstick[(i+1)%N]); Deadlock! Cycle: P0, C3, P3, C2, P2, C1, P1, C0, P0 P2 blocked Interrupt & Context switch

  9. Fixing Dining Philosophers • Make philosophers grab both chopsticks they need atomically • Maybe pass around a token (lock) saying who can grab chopsticks • Make a philosopher give up a chopstick • Others?

  10. Better Semaphore Solution to Dining Philosophers void philosophersLife(int i){ while (1) { think(); if ( i < ((i-1) % NUM_PHILOSOPHERS))}{ wait(chopstick[i]); wait(chopstick[(i-1) % NUM_PHILOSOPHERS]); } else { wait(chopstick[(i-1) % NUM_PHILOSOPHERS]); wait(chopstick[i]); } eat(); signal(chopstick[i]); signal(chopstick[(i-1) % NUM_PHILOSOPHERS]); } } Always wait for low chopstick first Why better? philosopher 0 gets chopstick 0 philosopher 1 gets chopstick 1 …. philosopher N waits for chopstick 0 No circular wait! No deadlock!!

  11. P1 blocked Chopstick 2 P0 blocked Philosopher 2 Philosopher 0 Chopstick 3 Chopstick 0 P2 can still run, request & get chopstick 3, eat, release chopsticks 2 & 3 Philosopher 3 P3 blocked No Cycle in Resource Allocation Graph Philosopher 1 Chopstick 1 if ( i < ((i+1)%N))}{ wait(chopstick[i]); wait(chopstick[(i+1)%N]); } else { wait(chopstick[(i+1)%N]); wait(chopstick[i]); } No cycle! No deadlock! Philosopher 0 will eat, then 3, then 2, then 1

  12. Recall: Conditions for Deadlock • Deadlock can exist if and only if the following four conditions are met; • Mutual Exclusion – some resource must be held exclusively • Hold and Wait – some process must be holding one resource and waiting for another • No preemption – resources cannot be preempted • Circular wait – there must exist a set of processes (p1,p2, …pn) such that p1 is waiting for p2, p2 is waiting for p3, … pn is waiting for p1 • All these held in the Dining Philosopher’s first “solution” we proposed • Can’t really do anything about preventing mutual exclusion; so what are the other options?

  13. Preventing Hold and Wait(partial allocation) • Do not allow processes to hold a resource when requesting others • Make philosophers get both chopsticks at once • Window’s WaitForMultipleObjects • Make processes ask for all resources they need at the beginning • Disadvantage: May not need all resources the whole time • Can release them early but must hold until used • Make processes release any held resources before requesting more • Hard to program!

  14. Preventing No Preemption • Preemption (have to love those double negative  ) • Allow system to take back resources once granted • Make some philosopher give back a chopstick • Disadvantage: Hard to program • System figures out how to take away CPU and memory without breaking programmer’s illusion • How do you take away access to an open file or a lock once granted?? Would need API to notify program and then code to deal with the removal of the resource at arbitrary points in the code • Checkpoint and Rollback?

  15. Preventing Circular wait • Impose an ordering on the possible resources and require that processes request them in a specific order • How did we prevent deadlock in dining philosophers? • Numbered the chopsticks • Made philosophers ask for lowest number chopstick first • Disadvantage: • Hard to think of all types of resources in system and number them consistently for all cooperating processes • I use a resource X and Y , you use resource Y and Z and W, someone else uses W, T, R – which is resource 1? (shared files, databases, chopsticks, locks, events, …) • For threads in the same process or closely related processes often isn’t that bad

  16. Deadlock Avoidance • Avoidance vs Prevention? Both actually prevent deadlock • Deadlock Prevention does so by breaking one of the four necessary conditions • Deadlock Avoidance allows processes to make any request they want (not constrained in ways so as to break one of the four conditions) *as long as* they declare their maximum possible resource requests at the outset • Deadlock avoidance usually results in higher resource allocation by allowing more combinations of resource requests to proceed than deadlock prevention • Still deadlock avoidance can deny resource requests that would not actually lead to deadlock in practice • More on this later...

  17. Dining Philosophers Monitor monitor DP { /* diningPhilosophers */ enum Moods{thinking, hungry, eating}; Moods state[N]; /* N is Num_Philosophers */ condition self[N]; void pickup(int i); void putdown(int i) ; void test(int i) ; void init() { for (int i=0; i < N; i++) state[i] = thinking; } }

  18. Dining Philosophers Monitor /********************************************** * Consider philosopher i (pi): * state[i] is * thinking (don’t need resources), * hungry (want resources), * eating (have all needed resources) * self[i] is a condition variable for pi * used when i has to wait for resources * state[(i+N-1) % N] is * the state of the philosopher to pi’s right * state[(i+1) % N] is * the state of the philosopher to pi’s left *********************************************/

  19. Dining Philosophers Monitor void pickupChopsticks(int i) { state[i] = hungry; test[i]; if (state[i] != eating) self[i].wait(); } void putdownChopsticks(int i) { state[i] = thinking; // test left and right neighbors test((i+(N-1)) % N); test((i+1) % N); }

  20. Dining Philosophers Monitor void test(int i) { if ((state[(i+N-1) % N] != eating) && (state[i] == hungry) && (state[(i+1) % N] != eating)) { state[i] = eating; self[i].signal(); } } } /* end DP monitor */

  21. Dining Philosophers Each “philosopher” thread executes: void philosophersLife(int i) { while(1){ think(); DP.pickupChopsticks(); eat(); DP.putdownChopsticks(); } }

  22. Generalize to Messaging • Synchronization based on data transfer (atomic) across a channel • In general, messages can be used to express ordering/scheduling constraints • Wait for message before do X • Send message = signal • Direct extension to distributed systems

  23. Window’s Events & UNIX Signals • Window’s Events • Synchronization objects used somewhat like semaphores when they are used for ordering/scheduling constraints • One process/thread can wait for an event to be signaled by another process/thread • Recall: UNIX signals • Kill = send signal; Signal = catch signal • Many system defined but also signals left to user definition • Can be used for synchronization • Signal handler sets a flag • Main thread polls on the value of the flag • Busy wait though

  24. Window’s Events • Create/destroy HANDLE CreateEvent(   LPSECURITY_ATTRIBUTES lpsa, // security privileges (default = NULL)   BOOL bManualReset,          // TRUE if event must be reset manually   BOOL bInitialState,         // TRUE to create event in signaled state   LPTSTR lpszEventName );     // name of event (may be NULL) BOOL CloseHandle( hObject ); • Wait DWORD WaitForSingleObject( HANDLE hObject,         // object to wait for                           DWORD dwMilliseconds ); • Signal (all threads that wait on it receive) BOOL SetEvent( HANDLE hEvent ); //signal on BOOL ResetEvent( HANDLE hEvent ); //signal off

  25. Pthread’s Condition Variables • Create/destroy int pthread_cond_init (pthread_cond_t *cond, pthread_condattr_t *attr); int pthread_cond_destroy (pthread_cond_t *cond); • Wait int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mut); • Timed Wait int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mut, const struct timespec *abstime); • Signal int pthread_cond_signal (pthread_cond_t *cond); • Broadcast int pthread_cond_broadcast (pthread_cond_t *cond);

More Related