In the Beginning... Example Critical Sections / Mutual Exclusion Critical

In the Beginning... Example Critical Sections / Mutual Exclusion Critical

Temporal relations • Instructions executed by a single thread are totally CSE 451: Operating Systems ordered Spring 2013 – A < B < C < … • Absent synchronization, instructions executed by distinct threads must be considered unordered / Module 7 simultaneous Synchronization – Not X < X’, and not X’ < X Ed Lazowska [email protected] Allen Center 570 © 2013 Gribble, Lazowska, Levy, Zahorjan © 2013 Gribble, Lazowska, Levy, Zahorjan 2 Critical Sections / Mutual Exclusion Example: ExampleIn the beginning... • Sequences of instructions that may get incorrect main() Y-axis is “time.” results if executed simultaneously are called critical A sections Could be one CPU, could pthread_create() • (We also use the term race condition to refer to a be multiple CPUs (cores). situation in which the results depend on timing) B foo() A' • Mutual exclusion means “not simultaneous” – A < B or B < A • A < B < C – We don’t care which B' • A' < B' • Forcing mutual exclusion between two critical section C • A < A' executions is sufficient to ensure correct execution – • C == A' guarantees ordering • C == B' • One way to guarantee mutually exclusive execution is using locks © 2013 Gribble, Lazowska, Levy, Zahorjan 3 © 2013 Gribble, Lazowska, Levy, Zahorjan 4 CriticalCritical sections When do critical sections arise? is the “happens-before” relation • One common pattern: T1 T2 T1 T2 T1 T2 – read-modify-write of – a shared value (variable) – in code that can be executed concurrently (Note: There may be only one copy of the code (e.g., a procedure), but it can be executed by more than one thread at a time) • Shared variable: – Globals and heap-allocated variables – NOT local variables (which are on the stack) (Note: Never give a reference to a stack-allocated (local) variable to another thread, unless you’re superhumanly Possibly incorrect Correct Correct careful …) © 2013 Gribble, Lazowska, Levy, Zahorjan 5 © 2013 Gribble, Lazowska, Levy, Zahorjan 6 1 Example: buffer management Example: shared bank account • Threads cooperate in multithreaded programs • Suppose we have to implement a function to –to share resources, access shared data structures withdraw money from a bank account: • e.g., threads accessing a memory cache in a web server –also, to coordinate their execution int withdraw(account, amount) { • e.g., a disk reader thread hands off blocks to a network writer int balance = get_balance(account); // read thread through a circular buffer balance -= amount; // modify put_balance(account, balance); // write network spit out cash; disk writer } reader thread thread • Now suppose that you and your partner share a bank account with a balance of $100.00 circular – what happens if you both go to separate ATM machines, and buffer simultaneously withdraw $10.00 from the account? © 2013 Gribble, Lazowska, Levy, Zahorjan 7 © 2013 Gribble, Lazowska, Levy, Zahorjan 8 Interleaved schedules • Assume the bank’s application is multi-threaded • The problem is that the execution of the two threads • A random thread is assigned a transaction when that can be interleaved, assuming preemptive scheduling: transaction is submitted balance = get_balance(account); balance -= amount; int withdraw(account, amount) { int withdraw(account, amount) { Execution sequence context switch int balance = get_balance(account); int balance = get_balance(account); balance = get_balance(account); as seen by CPU balance -= amount; balance -= amount; balance -= amount; put_balance(account, balance); put_balance(account, balance); put_balance(account, balance); spit out cash; spit out cash; spit out cash; context switch } } put_balance(account, balance); spit out cash; • What’s the account balance after this sequence? – who’s happy, the bank or you? • How often is this sequence likely to occur? © 2013 Gribble, Lazowska, Levy, Zahorjan 9 © 2013 Gribble, Lazowska, Levy, Zahorjan 10 Other Execution Orders How About Now? • Which interleavings are ok? Which are not? int xfer(from, to, amt) { int xfer(from, to, amt) { withdraw( from, amt ); withdraw( from, amt ); int withdraw(account, amount) { int withdraw(account, amount) { deposit( to, amt ); deposit( to, amt ); int balance = get_balance(account); int balance = get_balance(account); } } balance -= amount; balance -= amount; put_balance(account, balance); put_balance(account, balance); spit out cash; spit out cash; • Morals: } } – Interleavings are hard to reason about • We make lots of mistakes • Control-flow analysis is hard for tools to get right – Identifying critical sections and ensuring mutually exclusive access is … “easier” © 2013 Gribble, Lazowska, Levy, Zahorjan 11 © 2013 Gribble, Lazowska, Levy, Zahorjan 12 2 Another example Correct critical section requirements • Correct critical sections have the following i++; i++; requirements – mutual exclusion • at most one thread is in the critical section – progress • if thread T is outside the critical section, then T cannot prevent thread S from entering the critical section – bounded waiting (no starvation) • if thread T is waiting on the critical section, then T will eventually enter the critical section – assumes threads eventually leave critical sections – performance • the overhead of entering and exiting the critical section is small with respect to the work being done within it © 2013 Gribble, Lazowska, Levy, Zahorjan 13 © 2013 Gribble, Lazowska, Levy, Zahorjan 14 Mechanisms for building critical sections Locks • Spinlocks • A lock is a memory object with two operations: – primitive, minimal semantics; used to build others – acquire(): obtain the right to enter the critical section • Semaphores (and non-spinning locks) – release(): give up the right to be in the critical section – basic, easy to get the hang of, somewhat hard to program • acquire() prevents progress of the thread until the with lock can be acquired • Monitors • (Note: terminology varies: acquire/release, – higher level, requires language support, implicit operations lock/unlock) – easier to program with; Java “synchronized()” as an example • Messages – simple model of communication and synchronization based on (atomic) transfer of data across a channel – direct application to distributed systems © 2013 Gribble, Lazowska, Levy, Zahorjan 15 © 2013 Gribble, Lazowska, Levy, Zahorjan 16 Acquire/Release Locks: Example Locks: Example execution • Threads pair up calls to acquire() and release() – between acquire()and release(), the thread holds the lock – acquire() does not return until the caller “owns” (holds) lock() the lock lock() Two choices: • at most one thread can hold a lock at a time • Spin – What happens if the calls aren’t paired (I acquire, but neglect • Block unlock() • (Spin-then-block) to release)? – What happens if the two threads acquire different locks (I think that access to a particular shared data structure is mediated by lock A, and you think it’s mediated by lock B)? unlock() • (granularity of locking) © 2013 Gribble, Lazowska, Levy, Zahorjan 17 © 2013 Gribble, Lazowska, Levy, Zahorjan 18 3 Using locks Roadmap … acquire(lock) • Where we are eventually going: balance = get_balance(account); int withdraw(account, amount) { balance -= amount; – The OS and/or the user-level thread package will provide acquire(lock); some sort of efficient primitive for user programs to utilize in balance = get_balance(account); acquire(lock) achieving mutual exclusion (for example, locks or balance -= amount; put_balance(account, balance); semaphores, used with condition variables) critical put_balance(account, balance); section release(lock); release(lock); balance = get_balance(account); – There may be higher-level constructs provided by a spit out cash; balance -= amount; programming language to help you get it right (for example, } put_balance(account, balance); monitors – which also utilize condition variables) release(lock); • But somewhere, underneath it all, there needs to be spit out cash; a way to achieve “hardware” mutual exclusion (for spit out cash; example, test-and-set used to implement spinlocks) • What happens when green tries to acquire the lock? – This mechanism will not be utilized by user programs – But it will be utilized in implementing what user programs see © 2013 Gribble, Lazowska, Levy, Zahorjan 19 © 2013 Gribble, Lazowska, Levy, Zahorjan 20 Spinlocks Implementing spinlocks (cont.) • How do we implement spinlocks? Here’s one attempt: • Problem is that implementation of spinlocks has critical sections, too! struct lock_t { int held = 0; – the acquire/release must be atomic } • atomic == executes as though it could not be interrupted void acquire(lock) { the caller “busy-waits”, • code that executes “all or nothing” while (lock->held); or spins, for lock to be lock->held = 1; released hence spinlock • Need help from the hardware } void release(lock) { – atomic instructions lock->held = 0; • test-and-set, compare-and-swap, … } – disable/reenable interrupts • to prevent context switches • Why doesn’t this work? – where is the race condition? © 2013 Gribble, Lazowska, Levy, Zahorjan 21 © 2013 Gribble, Lazowska, Levy, Zahorjan 22 Spinlocks redux: Hardware Test-and-Set Implementing spinlocks using Test-and-Set • CPU provides the following as one atomic instruction: • So, to fix our broken spinlocks: struct lock { bool test_and_set(bool *flag) { int held = 0; bool old = *flag; } *flag = True; void acquire(lock) { return old; while(test_and_set(&lock->held)); } } void release(lock) { lock->held = 0; • Remember, this is a single atomic instruction … } – mutual exclusion? (at most one thread

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    5 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us