Implementing Mutual Exclusion Andy Wang Operating Systems COP 4610 / CGS 5765.

Slides:



Advertisements
Similar presentations
Synchronization NOTE to instructors: it is helpful to walk through an example such as readers/writers locks for illustrating the use of condition variables.
Advertisements

Global Environment Model. MUTUAL EXCLUSION PROBLEM The operations used by processes to access to common resources (critical sections) must be mutually.
PROCESS SYNCHRONIZATION READINGS: CHAPTER 5. ISSUES IN COOPERING PROCESSES AND THREADS – DATA SHARING Shared Memory Two or more processes share a part.
Mutual Exclusion.
1 Mutual Exclusion: Primitives and Implementation Considerations.
Operating Systems ECE344 Ding Yuan Synchronization (I) -- Critical region and lock Lecture 5: Synchronization (I) -- Critical region and lock.
CS 162 Discussion Section Week 3. Who am I? Mosharaf Chowdhury Office 651 Soda 4-5PM.
CS444/CS544 Operating Systems Synchronization 2/21/2006 Prof. Searleman
CS444/CS544 Operating Systems Synchronization 2/16/2007 Prof. Searleman
5.6 Semaphores Semaphores –Software construct that can be used to enforce mutual exclusion –Contains a protected variable Can be accessed only via wait.
CS162 Operating Systems and Systems Programming Lecture 7 Mutual Exclusion, Semaphores, Monitors, and Condition Variables September 21, 2005 Prof. John.
Jonathan Walpole Computer Science Portland State University
Jonathan Walpole Computer Science Portland State University
CPS110: Implementing threads/locks on a uni-processor Landon Cox.
U NIVERSITY OF M ASSACHUSETTS, A MHERST Department of Computer Science Emery Berger University of Massachusetts, Amherst Operating Systems CMPSCI 377 Lecture.
Computer Science 162 Discussion Section Week 3. Agenda Project 1 released! Locks, Semaphores, and condition variables Producer-consumer – Example (locks,
Synchronization CSCI 444/544 Operating Systems Fall 2008.
Threads and Critical Sections Vivek Pai / Kai Li Princeton University.
1 Race Conditions/Mutual Exclusion Segment of code of a process where a shared resource is accessed (changing global variables, writing files etc) is called.
9/8/2015cse synchronization-p1 © Perkins DW Johnson and University of Washington1 Synchronization Part 1 CSE 410, Spring 2008 Computer Systems.
CS510 Concurrent Systems Introduction to Concurrency.
U NIVERSITY OF M ASSACHUSETTS, A MHERST Department of Computer Science Emery Berger University of Massachusetts, Amherst Operating Systems CMPSCI 377 Lecture.
Implementing Synchronization. Synchronization 101 Synchronization constrains the set of possible interleavings: Threads “agree” to stay out of each other’s.
Process Synchronization Continued 7.2 Critical-Section Problem 7.3 Synchronization Hardware 7.4 Semaphores.
© Janice Regan, CMPT 300, May CMPT 300 Introduction to Operating Systems Mutual Exclusion.
Semaphores and Bounded Buffer. Semaphores  Semaphore is a type of generalized lock –Defined by Dijkstra in the last 60s –Main synchronization primitives.
Chapter 28 Locks Chien-Chung Shen CIS, UD
COMP 111 Threads and concurrency Sept 28, Tufts University Computer Science2 Who is this guy? I am not Prof. Couch Obvious? Sam Guyer New assistant.
Operating Systems ECE344 Ashvin Goel ECE University of Toronto Mutual Exclusion.
COSC 3407: Operating Systems Lecture 7: Implementing Mutual Exclusion.
Chapter 6 – Process Synchronisation (Pgs 225 – 267)
CS 162 Discussion Section Week 2 (9/16 – 9/20). Who am I? Kevin Klues Office Hours:
CS 3204 Operating Systems Godmar Back Lecture 7. 12/12/2015CS 3204 Fall Announcements Project 1 due on Sep 29, 11:59pm Reading: –Read carefully.
CS399 New Beginnings Jonathan Walpole. 2 Concurrent Programming & Synchronization Primitives.
CSCI-375 Operating Systems Lecture Note: Many slides and/or pictures in the following are adapted from: slides ©2005 Silberschatz, Galvin, and Gagne Some.
U NIVERSITY OF M ASSACHUSETTS A MHERST Department of Computer Science Computer Systems Principles Synchronization Emery Berger and Mark Corner University.
1 Previous Lecture Overview  semaphores provide the first high-level synchronization abstraction that is possible to implement efficiently in OS. This.
Implementing Lock. From the Previous Lecture  The “too much milk” example shows that writing concurrent programs directly with load and store instructions.
CSC 660: Advanced Operating SystemsSlide #1 CSC 660: Advanced OS Synchronization.
CS510 Concurrent Systems Jonathan Walpole. Introduction to Concurrency.
Slides on threads borrowed by Chase Landon Cox. Thread states BlockedReady Running Thread is scheduled Thread is Pre-empted (or yields) Thread calls Lock.
Mutual Exclusion -- Addendum. Mutual Exclusion in Critical Sections.
CS162 Section 2. True/False A thread needs to own a semaphore, meaning the thread has called semaphore.P(), before it can call semaphore.V() False: Any.
CS162 Operating Systems and Systems Programming Lecture 4 Synchronization, Atomic operations, Locks, Semaphores September 12, 2011 Anthony D. Joseph and.
CSE 120 Principles of Operating
Sarah Diesburg Operating Systems COP 4610
CS703 – Advanced Operating Systems
Atomic Operations in Hardware
Atomic Operations in Hardware
Monitors, Condition Variables, and Readers-Writers
Lecture 12: Peterson’s Solution and Hardware Support
CSCI 511 Operating Systems Chapter 5 (Part B) Mutual Exclusion, Semaphores Dr. Frank Li.
January 31, 2011 Ion Stoica CS162 Operating Systems and Systems Programming Lecture 4 Synchronization, Atomic operations,
Sarah Diesburg Operating Systems COP 4610
Jonathan Walpole Computer Science Portland State University
UNIVERSITY of WISCONSIN-MADISON Computer Sciences Department
Critical section problem
Coordination Lecture 5.
Implementing Mutual Exclusion
February 6, 2013 Ion Stoica CS162 Operating Systems and Systems Programming Lecture 5 Semaphores, Conditional Variables.
Implementing Mutual Exclusion
Kernel Synchronization II
September 12, 2012 Ion Stoica CS162 Operating Systems and Systems Programming Lecture 5 Semaphores, Conditional Variables.
Lecture 12: Peterson’s Solution and Hardware Support
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
CS333 Intro to Operating Systems
September 19, 2018 Prof. Ion Stoica
Presentation transcript:

Implementing Mutual Exclusion Andy Wang Operating Systems COP 4610 / CGS 5765

From the Previous Lecture  The too-much-milk example shows that writing concurrent programs with load and store instructions (i.e., C assignment statements) is tricky  Programmers want to use higher- level operations, such as locks

Ways of Implementing Locks Locking primitives High-level atomic operations Locks, semaphores, monitors, send/receive Low-level atomic operations Load/store, interrupt disables, test_and_set  All implementations require some level of hardware support

Atomic Memory Load and Store  C assignment statements  Examples: too-much-milk solutions

Disable Interrupts (for Uniprocessors)  On a uniprocessor, –One way to make an operation atomic is to disallow a context switch to occur in the middle of an operation  Solution 1 Lock::Acquire() { // disable interrupts; } Lock::Release() { // enable interrupts; }

An Example lock  Acquire(); if (no milk) { // get milk } lock  Release();

Problems with Solution 1  A user-level program may not re- enable interrupts –The OS can no longer regain the control  No guarantees on the duration of interrupts; bad for real-time systems  Solution 1 will not work for more complex scenarios (nested locks)

Solution 2 class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts while (value != FREE) { // enable interrupts // disable interrupts } value = BUSY; // enable interrupts } Lock::Release() { // disable interrupts value = FREE; // enable interrupts }

Solution 2 class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts while (value != FREE) { // enable interrupts // disable interrupts } value = BUSY; // enable interrupts } Lock::Release() { // disable interrupts value = FREE; // enable interrupts } The lock is initially FREE.

Solution 2 class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts while (value != FREE) { // enable interrupts // disable interrupts } value = BUSY; // enable interrupts } Lock::Release() { // disable interrupts value = FREE; // enable interrupts } Check the lock value while interrupts are disabled.

Solution 2 class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts while (value != FREE) { // enable interrupts // disable interrupts } value = BUSY; // enable interrupts } Lock::Release() { // disable interrupts value = FREE; // enable interrupts } Re-enable interrupts inside the loop, so someone may have a chance to unlock.

Solution 2 class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts while (value != FREE) { // enable interrupts // disable interrupts } value = BUSY; // enable interrupts } Lock::Release() { // disable interrupts value = FREE; // enable interrupts } Disable the interrupts again before checking the lock.

Solution 2 class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts while (value != FREE) { // enable interrupts // disable interrupts } value = BUSY; // enable interrupts } Lock::Release() { // disable interrupts value = FREE; // enable interrupts } If no one is holding the lock, grab the lock.

Problems with Solution 2  It works for a single processor  It does not work on a multi- processor machine –Other CPUs can still enter the critical section

The test_and_set Operation  test_and_set also works on multiprocessors –Atomically reads a memory location –Sets it to 1 –Returns the old value of memory location

The test_and_set Operation value = 0; Lock::Acquire() { // while the previous value is BUSY, loop while (test_and_set(value) == 1); } Lock::Release() { value = 0; }

Problems with Mentioned Approaches  Busy-waiting: hogging CPU cycles while a thread is waiting for a lock –Very inefficient –Can be avoided with a waiting queue

Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts if (value != FREE) { // Queue the thread // Go to sleep } else { value = BUSY; } // enable interrupts } Lock::Release() { // disable interrupts if (someone is waiting) { // wake a thread // Put it on ready queue } else { value = FREE; } // enable interrupts }

Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts if (value != FREE) { // Queue the thread // Go to sleep } else { value = BUSY; } // enable interrupts } Lock::Release() { // disable interrupts if (someone is waiting) { // wake a thread // Put it on ready queue } else { value = FREE; } // enable interrupts } Thread 1 tries to grab the lock. Thread 1

Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts if (value != FREE) { // Queue the thread // Go to sleep } else { value = BUSY; } // enable interrupts } Lock::Release() { // disable interrupts if (someone is waiting) { // wake a thread // Put it on ready queue } else { value = FREE; } // enable interrupts } No more busy waiting… Thread 1

Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts if (value != FREE) { // Queue the thread // Go to sleep } else { value = BUSY; } // enable interrupts } Lock::Release() { // disable interrupts if (someone is waiting) { // wake a thread // Put it on ready queue } else { value = FREE; } // enable interrupts } Grab the lock. Thread 1

Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts if (value != FREE) { // Queue the thread // Go to sleep } else { value = BUSY; } // enable interrupts } Lock::Release() { // disable interrupts if (someone is waiting) { // wake a thread // Put it on ready queue } else { value = FREE; } // enable interrupts } Thread 1 goes on computing. Thread 1

Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts if (value != FREE) { // Queue the thread // Go to sleep } else { value = BUSY; } // enable interrupts } Lock::Release() { // disable interrupts if (someone is waiting) { // wake a thread // Put it on ready queue } else { value = FREE; } // enable interrupts } Thread 2 tries to grab the lock. Thread 2

Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts if (value != FREE) { // Queue the thread // Go to sleep } else { value = BUSY; } // enable interrupts } Lock::Release() { // disable interrupts if (someone is waiting) { // wake a thread // Put it on ready queue } else { value = FREE; } // enable interrupts } The lock is busy… Thread 2

Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts if (value != FREE) { // Queue the thread // Go to sleep } else { value = BUSY; } // enable interrupts } Lock::Release() { // disable interrupts if (someone is waiting) { // wake a thread // Put it on ready queue } else { value = FREE; } // enable interrupts } Put the thread 2 on a waiting queue. Thread 2

Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts if (value != FREE) { // Queue the thread // Go to sleep } else { value = BUSY; } // enable interrupts } Lock::Release() { // disable interrupts if (someone is waiting) { // wake a thread // Put it on ready queue } else { value = FREE; } // enable interrupts } Go to sleep. Wait for the princess charming…Context switch within the sleep. Thread 2

Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts if (value != FREE) { // Queue the thread // Go to sleep } else { value = BUSY; } // enable interrupts } Lock::Release() { // disable interrupts if (someone is waiting) { // wake a thread // Put it on ready queue } else { value = FREE; } // enable interrupts } Say thread 1 wants to release the lock (interrupts are already disabled by thread 2). Thread 1

Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts if (value != FREE) { // Queue the thread // Go to sleep } else { value = BUSY; } // enable interrupts } Lock::Release() { // disable interrupts if (someone is waiting) { // wake a thread // Put it on ready queue } else { value = FREE; } // enable interrupts } Hello? Is someone waiting there? Is someone waiting there? Thread 2 is waiting. Thread 1

Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts if (value != FREE) { // Queue the thread // Go to sleep } else { value = BUSY; } // enable interrupts } Lock::Release() { // disable interrupts if (someone is waiting) { // wake a thread // Put it on ready queue } else { value = FREE; } // enable interrupts } Put thread 2 on ready queue; context switch. Thread 1

Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts if (value != FREE) { // Queue the thread // Go to sleep } else { value = BUSY; } // enable interrupts } Lock::Release() { // disable interrupts if (someone is waiting) { // wake a thread // Put it on ready queue } else { value = FREE; } // enable interrupts } Thread 2: Who kissed me? I don’t do mornings… Thread 2

Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts if (value != FREE) { // Queue the thread // Go to sleep } else { value = BUSY; } // enable interrupts } Lock::Release() { // disable interrupts if (someone is waiting) { // wake a thread // Put it on ready queue } else { value = FREE; } // enable interrupts } Thread 2 is done with its computation. Thread 2

Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts if (value != FREE) { // Queue the thread // Go to sleep } else { value = BUSY; } // enable interrupts } Lock::Release() { // disable interrupts if (someone is waiting) { // wake a thread // Put it on ready queue } else { value = FREE; } // enable interrupts } Suppose no one else is waiting. Thread 2

Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts if (value != FREE) { // Queue the thread // Go to sleep } else { value = BUSY; } // enable interrupts } Lock::Release() { // disable interrupts if (someone is waiting) { // wake a thread // Put it on ready queue } else { value = FREE; } // enable interrupts } Release the lock. (Thread 1 has finished its work, so it’s okay.) Thread 2

Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts if (value != FREE) { // Queue the thread // Go to sleep } else { value = BUSY; } // enable interrupts } Lock::Release() { // disable interrupts if (someone is waiting) { // wake a thread // Put it on ready queue } else { value = FREE; } // enable interrupts } Warp 9, engage (let’s get out of here)… Thread 2

Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts if (value != FREE) { // Queue the thread // Go to sleep } else { value = BUSY; } // enable interrupts } Lock::Release() { // disable interrupts if (someone is waiting) { // wake a thread // Put it on ready queue } else { value = FREE; } // enable interrupts } Eventually, the kernel will context switch back to thread 1…Thread 1: What happened? Thread 1

So, What’s Going On?  Interrupt disable and enable operations occur across context switches (at the steady state)

So, What’s Going On? Thread A Thread B Disable interrupts Sleep Disable interrupts Sleep Return from sleep Enable interrupts Context switch Return from sleep Enable interrupts Context switch

Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts if (value != FREE) { // Queue the thread // Go to sleep } else { value = BUSY; } // enable interrupts } Lock::Release() { // disable interrupts if (someone is waiting) { // wake a thread // Put it on ready queue } else { value = FREE; } // enable interrupts } CPU scheduler FIFO queue Thread 1 Thread 2 Thread 3

Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts if (value != FREE) { // Queue the thread // Go to sleep } else { value = BUSY; } // enable interrupts } Lock::Release() { // disable interrupts if (someone is waiting) { // wake a thread // Put it on ready queue } else { value = FREE; } // enable interrupts } CPU scheduler FIFO queue Thread 1 Thread 2 Thread 3

Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts if (value != FREE) { // Queue the thread // Go to sleep } else { value = BUSY; } // enable interrupts } Lock::Release() { // disable interrupts if (someone is waiting) { // wake a thread // Put it on ready queue } else { value = FREE; } // enable interrupts } CPU scheduler FIFO queue Thread 2 Thread 3 Thread 1

Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts if (value != FREE) { // Queue the thread // Go to sleep } else { value = BUSY; } // enable interrupts } Lock::Release() { // disable interrupts if (someone is waiting) { // wake a thread // Put it on ready queue } else { value = FREE; } // enable interrupts } CPU scheduler FIFO queue Thread 2 Thread 3 Thread 1

Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts if (value != FREE) { // Queue the thread // Go to sleep } else { value = BUSY; } // enable interrupts } Lock::Release() { // disable interrupts if (someone is waiting) { // wake a thread // Put it on ready queue } else { value = FREE; } // enable interrupts } CPU scheduler FIFO queue Thread 2 Thread 3 Thread 1

Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts if (value != FREE) { // Queue the thread // Go to sleep } else { value = BUSY; } // enable interrupts } Lock::Release() { // disable interrupts if (someone is waiting) { // wake a thread // Put it on ready queue } else { value = FREE; } // enable interrupts } CPU scheduler FIFO queue Thread 2 Thread 3 Thread 1

Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts if (value != FREE) { // Queue the thread // Go to sleep } else { value = BUSY; } // enable interrupts } Lock::Release() { // disable interrupts if (someone is waiting) { // wake a thread // Put it on ready queue } else { value = FREE; } // enable interrupts } CPU scheduler FIFO queue Thread 2 Thread 3 Thread 1

Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts if (value != FREE) { // Queue the thread // Go to sleep } else { value = BUSY; } // enable interrupts } Lock::Release() { // disable interrupts if (someone is waiting) { // wake a thread // Put it on ready queue } else { value = FREE; } // enable interrupts } CPU scheduler FIFO queue Thread 2 Thread 3 Thread 1

Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts if (value != FREE) { // Queue the thread // Go to sleep } else { value = BUSY; } // enable interrupts } Lock::Release() { // disable interrupts if (someone is waiting) { // wake a thread // Put it on ready queue } else { value = FREE; } // enable interrupts } CPU scheduler FIFO queue Thread 3 Thread 2 Thread 1

Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts if (value != FREE) { // Queue the thread // Go to sleep } else { value = BUSY; } // enable interrupts } Lock::Release() { // disable interrupts if (someone is waiting) { // wake a thread // Put it on ready queue } else { value = FREE; } // enable interrupts } CPU scheduler FIFO queue Thread 3 Thread 2 Thread 1

Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts if (value != FREE) { // Queue the thread // Go to sleep } else { value = BUSY; } // enable interrupts } Lock::Release() { // disable interrupts if (someone is waiting) { // wake a thread // Put it on ready queue } else { value = FREE; } // enable interrupts } CPU scheduler FIFO queue Thread 1 Thread 3 Thread 2

Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts if (value != FREE) { // Queue the thread // Go to sleep } else { value = BUSY; } // enable interrupts } Lock::Release() { // disable interrupts if (someone is waiting) { // wake a thread // Put it on ready queue } else { value = FREE; } // enable interrupts } CPU scheduler FIFO queue Thread 1 Thread 2 Thread 3

Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts if (value != FREE) { // Queue the thread // Go to sleep } else { value = BUSY; } // enable interrupts } Lock::Release() { // disable interrupts if (someone is waiting) { // wake a thread // Put it on ready queue } else { value = FREE; } // enable interrupts } CPU scheduler FIFO queue Thread 1 Thread 3 Thread 2

Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts if (value != FREE) { // Queue the thread // Go to sleep } else { value = BUSY; } // enable interrupts } Lock::Release() { // disable interrupts if (someone is waiting) { // wake a thread // Put it on ready queue } else { value = FREE; } // enable interrupts } CPU scheduler FIFO queue Thread 1 Thread 3 Thread 2

Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts if (value != FREE) { // Queue the thread // Go to sleep } else { value = BUSY; } // enable interrupts } Lock::Release() { // disable interrupts if (someone is waiting) { // wake a thread // Put it on ready queue } else { value = FREE; } // enable interrupts } CPU scheduler FIFO queue Thread 2 Thread 3

Locks Using Interrupt Disables, Without Busy-Waiting class Lock { int value = FREE; } Lock::Acquire() { // disable interrupts if (value != FREE) { // Queue the thread // Go to sleep } else { value = BUSY; } // enable interrupts } Lock::Release() { // disable interrupts if (someone is waiting) { // wake a thread // Put it on ready queue } else { value = FREE; } // enable interrupts } CPU scheduler FIFO queue Thread 2

Locks Using test_and_set, With Minimal Busy-Waiting  Impossible to use test_and_set to avoid busy-waiting  However, waiting can be minimized –with a waiting queue

Locks Using test_and_set, With Minimal Busy-Waiting class Lock { int value = FREE; int guard = 0; int guard = 0;} Lock::Acquire() { while (test_and_set(guard)); if (value != FREE) { // queue the thread // guard = 0 and sleep } else { value = BUSY; } guard = 0; } Lock::Release() { while (test_and_set(guard)); if (anyone waiting) { // wake up one thread // put it on ready queue } else { value = FREE; } guard = 0; }