CSE 451: Operating Systems Winter 2004 Module 6 Synchronization

Slides:



Advertisements
Similar presentations
Operating Systems ECE344 Midterm review Ding Yuan
Advertisements

Ch. 7 Process Synchronization (1/2) I Background F Producer - Consumer process :  Compiler, Assembler, Loader, · · · · · · F Bounded buffer.
Chapter 6: Process Synchronization
Background Concurrent access to shared data can lead to inconsistencies Maintaining data consistency among cooperating processes is critical What is wrong.
5.1 Silberschatz, Galvin and Gagne ©2009 Operating System Concepts with Java – 8 th Edition Chapter 5: CPU Scheduling.
Silberschatz, Galvin and Gagne ©2009 Operating System Concepts – 8 th Edition, Chapter 6: Process Synchronization.
Process Synchronization. Module 6: Process Synchronization Background The Critical-Section Problem Peterson’s Solution Synchronization Hardware Semaphores.
CSE 451: Operating Systems Winter 2012 Synchronization Mark Zbikowski Gary Kimura.
CSE 451: Operating Systems Spring 2012 Module 7 Synchronization Ed Lazowska Allen Center 570.
Synchronization. Shared Memory Thread Synchronization Threads cooperate in multithreaded environments – User threads and kernel threads – Share resources.
Operating Systems ECE344 Ding Yuan Synchronization (I) -- Critical region and lock Lecture 5: Synchronization (I) -- Critical region and lock.
CS444/CS544 Operating Systems Synchronization 2/16/2006 Prof. Searleman
1 Synchronization Coordinating the Activity of Mostly Independent Entities.
Race Conditions CS550 Operating Systems. Review So far, we have discussed Processes and Threads and talked about multithreading and MPI processes by example.
A. Frank - P. Weisberg Operating Systems Introduction to Cooperating Processes.
Synchronization CSCI 444/544 Operating Systems Fall 2008.
Operating Systems CSE 411 CPU Management Oct Lecture 13 Instructor: Bhuvan Urgaonkar.
1 CENG334 Introduction to Operating Systems Erol Sahin Dept of Computer Eng. Middle East Technical University Ankara, TURKEY URL:
Implementing Synchronization. Synchronization 101 Synchronization constrains the set of possible interleavings: Threads “agree” to stay out of each other’s.
© Janice Regan, CMPT 300, May CMPT 300 Introduction to Operating Systems Mutual Exclusion.
Operating Systems ECE344 Ashvin Goel ECE University of Toronto Mutual Exclusion.
1 CENG334 Introduction to Operating Systems Erol Sahin Dept of Computer Eng. Middle East Technical University Ankara, TURKEY URL:
CENG334 Introduction to Operating Systems
Chapter 6 – Process Synchronisation (Pgs 225 – 267)
CS399 New Beginnings Jonathan Walpole. 2 Concurrent Programming & Synchronization Primitives.
CSE 153 Design of Operating Systems Winter 2015 Midterm Review.
IT 344: Operating Systems Module 6 Synchronization Chia-Chi Teng CTB 265.
CSE 153 Design of Operating Systems Winter 2015 Lecture 5: Synchronization.
1 CSE451 Basic Synchronization Autumn 2002 Gary Kimura Lecture #7 & 8 October 14 & 16, 2002.
Implementing Lock. From the Previous Lecture  The “too much milk” example shows that writing concurrent programs directly with load and store instructions.
CS 153 Design of Operating Systems Winter 2016 Lecture 7: Synchronization.
CSCI1600: Embedded and Real Time Software Lecture 17: Concurrent Programming Steven Reiss, Fall 2015.
Implementing Mutual Exclusion Andy Wang Operating Systems COP 4610 / CGS 5765.
13/03/07Week 21 CENG334 Introduction to Operating Systems Erol Sahin Dept of Computer Eng. Middle East Technical University Ankara, TURKEY URL:
CSE 451: Operating Systems Spring 2010 Module 7 Synchronization John Zahorjan Allen Center 534.
Chapter 5 Concurrency: Mutual Exclusion and Synchronization Operating Systems: Internals and Design Principles, 6/E William Stallings Patricia Roy Manatee.
CSE 120 Principles of Operating
CS703 – Advanced Operating Systems
Background on the need for Synchronization
Synchronization.
Synchronization.
Chapter 5: Process Synchronization
CSCI 511 Operating Systems Chapter 5 (Part C) Monitor
CS703 – Advanced Operating Systems
UNIVERSITY of WISCONSIN-MADISON Computer Sciences Department
Lecture 2 Part 2 Process Synchronization
Critical section problem
Background and Motivation
Synchronization, Monitors, Deadlocks
CENG334 Introduction to Operating Systems
Implementing Mutual Exclusion
Implementing Mutual Exclusion
CSE 451: Operating Systems Winter 2007 Module 6 Synchronization
Kernel Synchronization II
CSE 451: Operating Systems Autumn 2004 Module 6 Synchronization
CSE 451: Operating Systems Autumn 2003 Lecture 7 Synchronization
CSE 451: Operating Systems Autumn 2005 Lecture 7 Synchronization
CSE 451: Operating Systems Winter 2003 Lecture 7 Synchronization
CSE 153 Design of Operating Systems Winter 19
CSE 153 Design of Operating Systems Winter 2019
CS333 Intro to Operating Systems
Chapter 6: Synchronization Tools
CSE 451: Operating Systems Spring 2008 Module 7 Synchronization
CSE 451: Operating Systems Winter 2007 Module 6 Synchronization
CSCI1600: Embedded and Real Time Software
CSE 451: Operating Systems Autumn 2009 Module 7 Synchronization
CSE 153 Design of Operating Systems Winter 2019
CSE 451: Operating Systems Spring 2007 Module 7 Synchronization
CSE 542: Operating Systems
CSE 542: Operating Systems
Presentation transcript:

CSE 451: Operating Systems Winter 2004 Module 6 Synchronization Ed Lazowska lazowska@cs.washington.edu Allen Center 570 1

© 2004 Ed Lazowska & Hank Levy Synchronization Threads cooperate in multithreaded programs to share resources, access shared data structures e.g., threads accessing a memory cache in a web server also, to coordinate their execution e.g., a disk reader thread hands off blocks to a network writer thread through a circular buffer network writer thread disk reader thread circular buffer 4/17/2019 © 2004 Ed Lazowska & Hank Levy

© 2004 Ed Lazowska & Hank Levy For correctness, we have to control this cooperation must assume threads interleave executions arbitrarily and at different rates scheduling is not under application writers’ control We control cooperation using synchronization enables us to restrict the interleaving of executions Note: this also applies to processes, not just threads (I’ll almost never say “process” again!) It also applies across machines in a distributed system 4/17/2019 © 2004 Ed Lazowska & Hank Levy

© 2004 Ed Lazowska & Hank Levy Shared resources We’ll focus on coordinating access to shared resources basic problem: two concurrent threads are accessing a shared variable if the variable is read/modified/written by both threads, then access to the variable must be controlled otherwise, unexpected results may occur Over the next several lectures, we’ll look at: mechanisms to control access to shared resources low level mechanisms like locks higher level mechanisms like mutexes, semaphores, monitors, and condition variables patterns for coordinating access to shared resources bounded buffer, producer-consumer, … 4/17/2019 © 2004 Ed Lazowska & Hank Levy

© 2004 Ed Lazowska & Hank Levy The classic example Suppose we have to implement a function to withdraw money from a bank account: int withdraw(account, amount) { balance = get_balance(account); balance -= amount; put_balance(account, balance); return balance; } Now suppose that you and your S.O. share a bank account with a balance of $100.00 what happens if you both go to separate ATM machines, and simultaneously withdraw $10.00 from the account? 4/17/2019 © 2004 Ed Lazowska & Hank Levy

© 2004 Ed Lazowska & Hank Levy Represent the situation by creating a separate thread for each person to do the withdrawals have both threads run on the same bank mainframe: int withdraw(account, amount) { balance = get_balance(account); balance -= amount; put_balance(account, balance); return balance; } int withdraw(account, amount) { balance = get_balance(account); balance -= amount; put_balance(account, balance); return balance; } 4/17/2019 © 2004 Ed Lazowska & Hank Levy

Interleaved schedules The problem is that the execution of the two threads can be interleaved, assuming preemptive scheduling: What’s the account balance after this sequence? who’s happy, the bank or you? ;) balance = get_balance(account); balance -= amount; context switch Execution sequence as seen by CPU balance = get_balance(account); balance -= amount; put_balance(account, balance); context switch put_balance(account, balance); 4/17/2019 © 2004 Ed Lazowska & Hank Levy

© 2004 Ed Lazowska & Hank Levy The crux of the matter The problem is that two concurrent threads (or processes) access a shared resource (account) without any synchronization creates a race condition output is non-deterministic, depends on timing We need mechanisms for controlling access to shared resources in the face of concurrency so we can reason about the operation of programs essentially, re-introducing determinism Synchronization is necessary for any shared data structure buffers, queues, lists, hash tables, … 4/17/2019 © 2004 Ed Lazowska & Hank Levy

Which resources are shared? Local variables are not shared refer to data on the stack, each thread has its own stack never pass/share/store a pointer to a local variable on another thread’s stack Global variables are shared stored in the static data segment, accessible by any thread Dynamic objects are shared stored in the heap, shared if you can name it in C, can conjure up the pointer e.g., void *x = (void *) 0xDEADBEEF in Java, strong typing prevents this must pass references explicitly 4/17/2019 © 2004 Ed Lazowska & Hank Levy

© 2004 Ed Lazowska & Hank Levy Mutual exclusion We want to use mutual exclusion to synchronize access to shared resources Code that uses mutual exclusion to synchronize its execution is called a critical section only one thread at a time can execute in the critical section all other threads are forced to wait on entry when a thread leaves a critical section, another can enter The critical section problem is “how do you implement critical sections?” 4/17/2019 © 2004 Ed Lazowska & Hank Levy

Critical section requirements A solution to the critical section problem should meet the following 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 4/17/2019 © 2004 Ed Lazowska & Hank Levy

Mechanisms for building critical sections Locks very primitive, minimal semantics; used to build others Semaphores basic, easy to get the hang of, hard to program with Monitors high level, requires language support, implicit operations easy to program with; Java “synchronized()” as example Messages simple model of communication and synchronization based on (atomic) transfer of data across a channel direct application to distributed systems 4/17/2019 © 2004 Ed Lazowska & Hank Levy

© 2004 Ed Lazowska & Hank Levy Locks A lock is a object (in memory) that provides the following two operations: acquire( ): a thread calls this before entering a critical section release( ): a thread calls this after leaving a critical section Threads pair up calls to acquire( ) and release( ) between acquire( ) and release( ), the thread holds the lock acquire( ) does not return until the caller holds the lock at most one thread can hold a lock at a time (usually) so: what can happen if the calls aren’t paired? Two basic flavors of locks spinlock blocking (a.k.a. “mutex”) 4/17/2019 © 2004 Ed Lazowska & Hank Levy

© 2004 Ed Lazowska & Hank Levy Using locks acquire(lock) balance = get_balance(account); balance -= amount; int withdraw(account, amount) { acquire(lock); balance = get_balance(account); balance -= amount; put_balance(account, balance); release(lock); return balance; } acquire(lock) critical section put_balance(account, balance); release(lock); balance = get_balance(account); balance -= amount; put_balance(account, balance); release(lock); What happens when green tries to acquire the lock? Why is the “return” outside the critical section? is this ok? 4/17/2019 © 2004 Ed Lazowska & Hank Levy

Spinlocks How do we implement locks? Here’s one attempt: Why doesn’t this work? where is the race condition? struct lock { int held = 0; } void acquire(lock) { while (lock->held); lock->held = 1; void release(lock) { lock->held = 0; the caller “busy-waits”, or spins for lock to be released, hence spinlock 4/17/2019 © 2004 Ed Lazowska & Hank Levy

Implementing locks (cont.) Problem is that implementation of locks has critical sections, too! the acquire/release must be atomic atomic == executes as though it could not be interrupted code that executes “all or nothing” Need help from the hardware atomic instructions test-and-set, compare-and-swap, … disable/reenable interrupts to prevent context switches 4/17/2019 © 2004 Ed Lazowska & Hank Levy

Spinlocks redux: Test-and-Set CPU provides the following as one atomic instruction: So, to fix our broken spinlocks, do: bool test_and_set(bool *flag) { bool old = *flag; *flag = True; return old; } struct lock { int held = 0; } void acquire(lock) { while(test_and_set(&lock->held)); void release(lock) { lock->held = 0; 4/17/2019 © 2004 Ed Lazowska & Hank Levy

© 2004 Ed Lazowska & Hank Levy Reminder of use … acquire(lock) balance = get_balance(account); balance -= amount; int withdraw(account, amount) { acquire(lock); balance = get_balance(account); balance -= amount; put_balance(account, balance); release(lock); return balance; } acquire(lock) critical section put_balance(account, balance); release(lock); balance = get_balance(account); balance -= amount; put_balance(account, balance); release(lock); How does a thread blocked on an “acquire” (that is, stuck in a test-and-set loop) yield the CPU? calls yield( ), or there’s an involuntary context switch 4/17/2019 © 2004 Ed Lazowska & Hank Levy

Problems with spinlocks Spinlocks work, but are horribly wasteful! if a thread is spinning on a lock, the thread holding the lock cannot make progress And neither can anyone else! Only want spinlocks as primitives to build higher-level synchronization constructs “Do not try this at home!” 4/17/2019 © 2004 Ed Lazowska & Hank Levy

Another approach: Disabling interrupts struct lock { } void acquire(lock) { cli(); // disable interrupts void release(lock) { sti(); // reenable interupts 4/17/2019 © 2004 Ed Lazowska & Hank Levy

Problems with disabling interrupts Only available to the kernel Can’t allow user-level to disable interrupts! Insufficient on a multiprocessor Each processor has its own interrupt mechanism “Long” periods with interrupts disabled can wreak havoc with devices Just as with spinlocks, only want to use disabling of interrupts to build higher-level synchronization constructs 4/17/2019 © 2004 Ed Lazowska & Hank Levy

© 2004 Ed Lazowska & Hank Levy Summary Synchronization can be provided by locks, semaphores, monitors, messages … Locks are the lowest-level mechanism very primitive in terms of semantics – error-prone implemented by spin-waiting (crude) or by disabling interrupts (also crude, and can only be done in the kernel) In our next exciting episode … semaphores are a slightly higher level abstraction less crude implementation too monitors are significantly higher level utilize programming language support to reduce errors 4/17/2019 © 2004 Ed Lazowska & Hank Levy