
“Too Many Cookies” ProBlem u Roommates Lance and James want a Bag of cookies in the room COS 318: Operating Systems at all times, but don’t’ want to Buy too many cookies u They Buy cookies independently, using the following sequence Synchronization: Mutual l Look in cabinet: Out of cookies Exclusion l Leave for Wawa to buy cookies l Arrive at Wawa Jaswinder Pal Singh and a FaBulous Course Staff l Buy a bag of cookies Computer Science Department l Arrive home and put cookies in cabinet Princeton University (http://www.cs.princeton.edu/courses/cos318/) 2 “Too Many Cookies” ProBlem Using A Note? James Lance James and Lance’s Cookie Optimization Algorithm: 15:00 Look in caBinet: out of cookies 15:05 Leave for Wawa if (noCookies) { // check if roommate left a note if (noNote) { 15:10 Arrive at Wawa Look in caBinet: out of cookies leave note; // let them know you went to Wawa 15:15 Buy a bag of cookies Leave for Wawa buy cookies; remove note; 15:20 Arrive home; put cookies away Arrive at Wawa } 15:25 Buy a bag of cookies } Arrive home; put cookies away u Any issue with this approach? u Oh No! Too many cookies. 3 4 1 Using A Note? Why Solution #1 Does Not Work James Lance James Lance 3:00 if (noCookies) { if (noCookies) { if (noCookies) { if (noNote) { if (noNote) { if (noNote) { 3:05 leave note; leave note; 3:10 if (noCookies) { buy cookies; buy cookies; 3:15 if (noNote) { remove note; remove note; 3:20 leave Note; leave Note; } } 3:25 buy cookies; buy cookies; } } 3:30 remove Note } } remove Note} } u Any issue with this approach? Threads can get context-switched at any time Too many cookies! 5 PossiBle Solution #2: Leave Note First PossiBle Solution #3: One Spin-waits u ProBlem was that threads checked once and moved on James Lance l So have one of them spin-wait on the note James Lance leave noteA leave noteB if (noNoteB) { if (noNoteA) { leave noteA leave noteB if (noCookies) { if(noCookies){ while (noteB) if (noNoteA) { buy cookies buy cookies do nothing; if (noCookies) { } } if (noCookies) buy cookies } } buy cookies; } remove noteA remove noteB remove noteA } remove noteB Didn’t buy cookies u Would this fix the proBlem? Didn’t buy u Yes, But complicated, different code for different threads, u Does this method work? cookies busy waiting wasteful, and not fair 7 8 2 Threads Example: Shared Counter ProBlem with Shared Counters u Google gets millions of hits a day. Uses multiple threads (on multiple processors) to speed things up. u One possiBle result: lost update! u Simple shared state error: each thread increments a hits = 0 shared counter to track the number of hits today: T2 time T1 … read hits (0) hits = hits + 1; read hits (0) … hits = 0 + 1 hits = 0 + 1 u What happens when two threads execute this code hits = 1 concurrently? ProBlem with Shared Counters Race Conditions u Race condition: accesses to shared state that can lead u Another possiBle result: everything works! to a timing dependent error hits = 0 l Whether it happens depends on how threads are scheduled T2 u Difficult to avoid Because: time T1 l Must make sure all possible schedules are safe. read hits (0) l NumBer of possiBle schedule permutations is huge. hits = 0 + 1 l One or more of them may Be “Bad” read hits (1) l They are intermittent hits = 1 + 1 l Timing dependent => small changes can hide or reveal Bug hits = 2 • Adding a print statement • Running on a different machine u Another possible result: everything works u This is called a “race condition” 3 It’s Actually Even Worse Preventing Race Conditions: Atomicity u Compilers reorder instruction issue within a thread u Atomic unit = instruction sequence guaranteed to l To optimize register usage and hence run code faster execute indivisibly (also called a “critical section”). • If two threads execute the same atomic unit at the same time, one u Hardware reorders instruction execution/completion thread will execute the whole sequence before the other begins l E.g. write Buffers, etc hits = 0 u All done to optimize execution speed T2 time T1 u But they don’t know aBout multiple threads and issues hits = hits + 1 across them hits = hits + 1 hits = 2 u How to make multiple instrs seem like an atomic one? 13 Providing Atomicity Preventing Race Conditions: Atomicity u Have hardware provide Better primitives than atomic u Counter proBlem load and store. Acquire(lock); u Build higher-level programming aBstractions on this new hits = hits + 1;) Critical section hardware support. Release(lock); u Example: locks Acquire --- wait until lock is free, then graB it Release --- unlock/release the lock, waking up a waiter if any These must Be atomic operations --- if two threads are waiting for the lock, and both see it is free, only one graBs it 17 4 Preventing Race Conditions: Atomicity Rules for Using Locks u Cookies proBlem u Lock is initially free u Always acquire Before accessing shared data structure Acquire(lock); if (noCookies) Critical section u Always release after finishing with shared data buy cookies; l Only the lock holder can release Release(lock); u Don’t access shared data without lock DesiraBle Properties: 1. At most one holder, or thread in critical section, at a time (safety) 2. If no one is holding the lock, an acquire gets the lock (progress) 3. If all lock holders finish and there are no higher priority waiters, waiter eventually gets the lock (progress) 18 Some Definitions Implementing Mutual Exclusion (Locks) u Sychronization: What makes a good solution? l Ensuring proper cooperation among threads l Mutual exclusion, event synchronization u Only one process/thread inside a critical section at a time u Mutual exclusion: u No assumptions need to be made about CPU speeds l Ensuring that only one thread does a particular thing at a time. One thread u A process/thread inside a critical section should not Be doing it excludes another from doing it at the same time. blocked by any process outside the critical section u Critical section: l Piece of code that only one thread can “Be in” at a given time. Only one u No one waits forever thread at a time will be allowed to get into the section of code. u Lock: prevents someone from doing something u Should work for multiprocessors l Lock before entering critical section, before accessing shared data l Unlock when leaving, after done accessing shared data u Should allow same code for all processes/threads l Wait if locked u Event synchronization: l Making sure an event in one thread does not happen Before/after an event in another thread 24 5 Simple Lock VariaBles Prevent Context Switches in Critical Section Acquire(lock) { Release(lock) { u On a uniprocessor, operations are atomic as long as a while (lock.value == 1) lock.value = 0; context switch doesn’t occur ; } lock.value = 1; u Context switches are caused either By actions the } thread takes (e.g. traps etc) or by external interrupts u Thread 1: Thread 2: The former can Be controlled Acquire(lock) { while (lock.value == 1) ; u DisaBle interrupts during certain portions of code? {context switch) Acquire(lock) { l Delay the handling of external events while (lock.value == 1) ; {context switch) lock.value = 1; } {context switch) lock.value = 1; } 25 26 Why EnaBle or DisaBle Interrupts DisaBling Interrupts for Critical Section? u Interrupts are important l Process I/O requests (e.g. keyBoard) Acquire(): disable interrupts Acquire() l Implement preemptive CPU scheduling Release(): enable interrupts critical section? u DisaBling interrupts can Be helpful Release() l Introduce uninterruptiBle code regions l Think sequentially most of the time l Delay handling of external events Issues: DisableInt() l Critical sections can Be arBitrarily long . Uninterruptible . region . EnableInt() 30 31 6 “DisaBle Interrupts” to Implement Mutex Fix “DisaBle Forever” problem? Acquire(lock) { Release(lock) { Acquire(lock) { Release(lock) { disable interrupts; disable interrupts; disable interrupts; disable interrupts; while (lock.value != 0) lock.value = 0; while (lock.value != 0){ lock.value = 0; ; enable interrupts; enable interrupts; enable interrupts; lock.value = 1; } disable interrupts; } enable interrupts; } } lock.value = 1; enable interrupts; u Don’t let acquire Be interrupted Before sets lock.value to 1 } l This was the proBlem when interrupts weren’t disaBled u EnaBle interrupts during spin loop u Don’t disaBle interrupts for entire critical section u DisaBle interrupts only when accessing lock.value u Issues: l Cannot Be interrupted after loop and Before setting value l May disaBle interrupts forever Issues: l Consume a lot of CPU cycles doing enable and disable 32 33 Another Implementation Atomic Operations u A thread executing an atomic instruction can’t Be Acquire(lock) { Release(lock) { disable interrupts; disable interrupts; preempted or interrupted while it’s doing it if (lock.value != 0) if (anyone in queue) { u Atomic operations on same memory value are serialized { Dequeue a thread; Enqueue me for lock; make it ready; l Even on multiprocessors! Yield(); } l Result is consistent with some sequential ordering of operations } lock.value = 0; lock.value = 1; enable interrupts; l Without atomic ops, simultaneous writes By different threads enable interrupts; } may produce a garBage value, or read that happens } simultaneously with a write may read garBage value Avoid Busy-waiting u Don’t usually require special privileges, can Be user level Issues l Interrupt based approaches don’t work for multiprocessors l Cannot allow user code to disaBle interrupts 34 35 7 Peterson’s Algorithm Atomic Read-Modify-Write
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages11 Page
-
File Size-