implementing lock

39
Implementing Lock Implementing Lock

Upload: palmer

Post on 25-Feb-2016

70 views

Category:

Documents


2 download

DESCRIPTION

Implementing Lock. From the Previous Lecture. The “too much milk” example shows that writing concurrent programs directly 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. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Implementing Lock

Implementing LockImplementing Lock

Page 2: Implementing Lock

From the Previous LectureFrom the Previous Lecture The “too much milk” example shows The “too much milk” example shows

that writing concurrent programs that writing concurrent programs directly with load and store directly with load and store instructions (i.e., C assignment instructions (i.e., C assignment statements) is trickystatements) is tricky

Programmers want to use higher-Programmers want to use higher-level operations, such as lockslevel operations, such as locks

Page 3: Implementing Lock

Ways of Implementing LocksWays of Implementing Locks

Locking primitivesLocking primitivesHigh-level atomic High-level atomic operationsoperations

Locks, semaphores, Locks, semaphores, monitors, send and monitors, send and receivereceive

Low-level atomic Low-level atomic operationsoperations

Load/store, interrupt Load/store, interrupt disables, disables, test_and_settest_and_set

All implementations require some All implementations require some level of hardware supportlevel of hardware support

Page 4: Implementing Lock

Atomic Memory Load and StoreAtomic Memory Load and Store C assignment statementsC assignment statements Examples: “too much milk” solutionsExamples: “too much milk” solutions

Page 5: Implementing Lock

Disable Interrupts (for Disable Interrupts (for Uniprocessors)Uniprocessors)

On a uniprocessor,On a uniprocessor,– An operation is atomic as long as a An operation is atomic as long as a

context switch does not occur in the context switch does not occur in the middle of an operationmiddle of an operation

Solution 1Solution 1Lock::Acquire() {Lock::Acquire() {

// disable interrupts;// disable interrupts;}}Lock::Release() {Lock::Release() {

// enable interrupts;// enable interrupts; }}

Page 6: Implementing Lock

An ExampleAn Example

locklockAcquire();Acquire();if (no milk) {if (no milk) {

// get milk// get milk}}locklockRelease();Release();

Page 7: Implementing Lock

Problems with Solution 1Problems with Solution 1 A user-level program may not re-A user-level program may not re-

enable interruptsenable interrupts– The kernel can no longer regain the The kernel can no longer regain the

controlcontrol No guarantees on the duration of No guarantees on the duration of

interrupts; bad for real-time systemsinterrupts; bad for real-time systems Solution 1 will not work for more Solution 1 will not work for more

complex scenarios (nested locks)complex scenarios (nested locks)

Page 8: Implementing Lock

Solution 2Solution 2class Lock {class Lock {

int value = FREE;int value = FREE;}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptswhile (value != FREE) {while (value != FREE) {

// enable interrupts// enable interrupts// disable interrupts// disable interrupts

}}value = BUSY;value = BUSY;// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsvalue = FREE;value = FREE;// enable interrupts// enable interrupts

}}

Page 9: Implementing Lock

Solution 2Solution 2class Lock {class Lock {

int value = FREE;int value = FREE;}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptswhile (value != FREE) {while (value != FREE) {

// enable interrupts// enable interrupts// disable interrupts// disable interrupts

}}value = BUSY;value = BUSY;// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsvalue = FREE;value = FREE;// enable interrupts// enable interrupts

}}

The lock is initially FREE.

Page 10: Implementing Lock

Solution 2Solution 2class Lock {class Lock {

int value = FREE;int value = FREE;}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptswhile (while (value != FREEvalue != FREE) {) {

// enable interrupts// enable interrupts// disable interrupts// disable interrupts

}}value = BUSY;value = BUSY;// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsvalue = FREE;value = FREE;// enable interrupts// enable interrupts

}}

Check the lock value whileinterrupts are disabled.

Page 11: Implementing Lock

Solution 2Solution 2class Lock {class Lock {

int value = FREE;int value = FREE;}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptswhile (value != FREE) {while (value != FREE) {

// enable interrupts// enable interrupts// disable interrupts// disable interrupts

}}value = BUSY;value = BUSY;// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsvalue = FREE;value = FREE;// enable interrupts// enable interrupts

}}

Re-enable interrupts inside theloop, so someone may have a chance to unlock.

Page 12: Implementing Lock

Solution 2Solution 2class Lock {class Lock {

int value = FREE;int value = FREE;}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptswhile (value != FREE) {while (value != FREE) {

// enable interrupts// enable interrupts// disable interrupts// disable interrupts

}}value = BUSY;value = BUSY;// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsvalue = FREE;value = FREE;// enable interrupts// enable interrupts

}}

Disable the interrupts againbefore checking the lock.

Page 13: Implementing Lock

Solution 2Solution 2class Lock {class Lock {

int value = FREE;int value = FREE;}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptswhile (value != FREE) {while (value != FREE) {

// enable interrupts// enable interrupts// disable interrupts// disable interrupts

}}value = BUSY;value = BUSY;// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsvalue = FREE;value = FREE;// enable interrupts// enable interrupts

}}

If no one is holding the lock, grab the lock.

Page 14: Implementing Lock

Problems with Solution 2Problems with Solution 2 It works for a single processorIt works for a single processor It does not work on a multi-processor It does not work on a multi-processor

machinemachine– Other CPUs can still enter the critical Other CPUs can still enter the critical

sectionsection

Page 15: Implementing Lock

The The test_and_settest_and_set Operation Operation test_and_settest_and_set also works on also works on

multiprocessorsmultiprocessors– Atomically reads a memory locationAtomically reads a memory location– Sets it to 1Sets it to 1– Returns the old value of memory Returns the old value of memory

locationlocation

Page 16: Implementing Lock

The The test_and_settest_and_set Operation Operationvalue = 0;value = 0;

Lock::Acquire() {Lock::Acquire() {// while the previous value is BUSY, loop// while the previous value is BUSY, loopwhile (test_and_set(value) == 1);while (test_and_set(value) == 1);

}}

Lock::Release() {Lock::Release() {value = 0;value = 0;

}}

Page 17: Implementing Lock

Common Problems with Mentioned Common Problems with Mentioned ApproachesApproaches

Busy-waitingBusy-waiting: consumption of CPU : consumption of CPU cycles while a thread is waiting for a cycles while a thread is waiting for a locklock– Very inefficientVery inefficient– Can be avoided with a waiting queueCan be avoided with a waiting queue

Page 18: Implementing Lock

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsif (value != FREE) {if (value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

Page 19: Implementing Lock

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsifif (value != FREE) { (value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

Thread 1 tries to grab the lock.

Page 20: Implementing Lock

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsifif (value != FREE) { (value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

No more busy waiting…

Page 21: Implementing Lock

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsifif (value != FREE) { (value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

Grab the lock.

Page 22: Implementing Lock

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsifif (value != FREE) { (value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

Thread 1 goes on computing.

Page 23: Implementing Lock

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsifif (value != FREE) { (value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

Thread 2 tries to grab the lock.

Page 24: Implementing Lock

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsifif (value != FREE) {(value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

The lock is busy…

Page 25: Implementing Lock

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsifif (value != FREE) { (value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

Put the thread 2 on a waiting queue.

Page 26: Implementing Lock

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsifif (value != FREE) { (value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

Go to sleep. Wait for the princesscharming…Context switch within the sleep.

Page 27: Implementing Lock

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsifif (value != FREE) { (value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

Say thread 1 wants to release the lock.

Page 28: Implementing Lock

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsifif (value != FREE) { (value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

Hello? Is someone waiting there? <echo> Is someone waiting there?Thread 2 is waiting.

Page 29: Implementing Lock

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsifif (value != FREE) { (value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

Put thread 2 on ready queue; context switch.

Page 30: Implementing Lock

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsifif (value != FREE) { (value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

Thread 2: Who kissed me? I don’t do mornings…

Page 31: Implementing Lock

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsifif (value != FREE) { (value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

Thread 2 is done with its computation.

Page 32: Implementing Lock

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsifif (value != FREE) { (value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

Suppose no one else is waiting.

Page 33: Implementing Lock

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsifif (value != FREE) { (value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

Release the lock. (Thread 1 hasfinished its work, so it’s okay.)

Page 34: Implementing Lock

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsifif (value != FREE) { (value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

Warp 9, engage (let’s get out of here)…

Page 35: Implementing Lock

Locks Using Interrupt Disables, Locks Using Interrupt Disables, Without Busy-WaitingWithout Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {// disable interrupts// disable interruptsifif (value != FREE) { (value != FREE) {

// Queue the thread// Queue the thread// Go to sleep// Go to sleep

} else {} else {value = BUSY;value = BUSY;

}}// enable interrupts// enable interrupts

}}

Lock::Release() {Lock::Release() {// disable interrupts// disable interruptsif (someone is waiting) {if (someone is waiting) {

// wake a thread// wake a thread// Put it on ready // Put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}// enable interrupts// enable interrupts

}}

Eventually, the kernel will contextswitch back to thread 1…Thread 1: What happened?

Page 36: Implementing Lock

So, What’s Going On?So, What’s Going On? Interrupt disable and enable Interrupt disable and enable

operations occur across context operations occur across context switches (at the steady state)switches (at the steady state)

Page 37: Implementing Lock

So, What’s Going On?So, What’s Going On?

Thread AThread A Thread BThread BAcquire() { Disable interrupts Sleep

Release() { Disable interrupts Put A in ready queue enable interrupt}

Context switch

Return from sleepEnable interrupts}

Context switch

Enable interrupts……

Page 38: Implementing Lock

Locks Using Locks Using test_and_settest_and_set, With , With Minimal Busy-WaitingMinimal Busy-Waiting

Impossible to use Impossible to use test_and_settest_and_set to to avoid busy-waitingavoid busy-waiting

However, waiting can be minimized However, waiting can be minimized with a waiting queuewith a waiting queue

Page 39: Implementing Lock

Locks Using Locks Using test_and_settest_and_set, With , With Minimal Busy-WaitingMinimal Busy-Waiting

class Lock {class Lock {int value = FREE;int value = FREE;

}}

Lock::Acquire() {Lock::Acquire() {while (test_and_set(guard));while (test_and_set(guard));if (value != FREE) {if (value != FREE) {

// queue the thread// queue the thread// guard = 0 and // guard = 0 and

sleepsleep} else {} else {

value = BUSY;value = BUSY;}}guard = 0;guard = 0;

}}

Lock::Release() {Lock::Release() {while (test_and_set(guard));while (test_and_set(guard));if (anyone waiting) {if (anyone waiting) {

// wake up one thread// wake up one thread// put it on ready // put it on ready

queuequeue} else {} else {

value = FREE;value = FREE;}}guard = 0;guard = 0;

}}